⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 scmds.c

📁 P2P NAP的C实现 P2P在网络应用中越来越流行
💻 C
📖 第 1 页 / 共 4 页
字号:
  /* see if global or per-user upload limit exceeded */  r = upload_limit_reached(tok[0]);  if (r) {    /* sendpack(s, NAP_GFR, "%s", str); */ /* why is this here ? */     /* apparently the official napster server does not forward QLIMIT       packets to the requestor, thus keeping them waiting       forever. However, this is too bad, I don't think we should use       NAP_GFR here. Do the opennap servers react differently? ### check       this another time. */    sendpack(s, NAP_QLIMIT, "%s \"%s\" %li", tok[0], tok[1], r==2 ? nvar("maxuploads") : nvar("maxupuser"));    if (nvar_default("showtoomanyuploads", 0)) {      wp(win, "%s* Too many uploads %s(can't send \"%s\" to %s)%s\n", RED, r==2 ? "" : "for this user ", tok[1], tok[0], WHITE);      drw(win);    }    free(lfn);    return(1);  }  /* otherwise, accept the upload. Create an item in the upload list */  task = (upload_t *)malloc(sizeof(upload_t));  task->state = WAITING;  task->nick = strdup(tok[0]);  task->rfn = strdup(tok[1]);  task->fn = strdup(fn);  task->lfn = lfn;  /* already allocated with strdup */  task->linespeed = num>=3 ? atoi(tok[2]) : 0;  task->c_time = time(0);  /* add it to the upload list */  list_append(upload_t, up, task);  /* sendpack(s, NAP_SX, "%s", task->nm); */ /* why send a link speed query? */  /* accept upload request: <nick> "<filename>" */  sendpack(s, NAP_GFR, "%s", str);   return(1);}/* link speed response: <nick> <linespeed> */I_NAP_FUNC(sry){  return(1);}/* 501 (0x1f5) alternate download ack:  * <nick> <ip> <port> "<filename>" <md5> <speed> * we are being asked to UPLOAD a file to a remote client (presumably * because we are firewalled and cannot accept incoming connections) */I_NAP_FUNC(ssf){  upload_t *task;  sock_t *sk=NULL;  int k, r;  struct sockaddr_in dst;    /* find the corresponding upload */  list_find(task, up, task->state == WAITING && !strcasecmp(task->nick, tok[0]) && !strcasecmp(task->rfn, tok[3]));  if (!task) {     /* we were not waiting for this upload. Ignore silently. */    /* note: if in the future, we choose to accept 501 without prior 607, we       must then also do the security checks; check the file is actually       shared, /tquit is not active, etc */    return(1);  }    /* contact remote client */  /* note: the integer which represents the IP address is sent by the   * napster protocol in "twisted" form. For instance, 1.0.0.0 = 1,   * 0.1.0.0 = 256, etc.  If this integer is stored in its native   * format on a given host, it will end up representing the IP   * address in *non-host* byte order. On little-endian machines, such   * as x86 and Alpha, this happens to be the correct network   * byteorder (=big-endian), but on big-endian machines, it is   * not. Thus, the correct thing to do is to first swap the byte   * order to convert from *non-host* to *host* byte order, then apply   * htonl(3) to convert from *host* to *network* byte order. This   * causes some unnecessary work on little-endian machines, but   * to heck with that. -PS */  dst.sin_addr.s_addr = htonl(swapl(strtoul(tok[1], (char **)NULL, 10)));  dst.sin_port = htons(atoi(tok[2]));  dst.sin_family = AF_INET;    k = socket(AF_INET, SOCK_STREAM, 0);    /* use non-blocking i/o so that connect will not hang */  fcntl(k, F_SETFL, O_NONBLOCK);  r = connect(k, (struct sockaddr *)&dst, sizeof(dst));  if (r == -1 && errno != EINPROGRESS) {    wp(win, ""RED"* Error sending file (%s) to %s: %s"WHITE"\n", task->fn, task->nick, strerror(errno));    drw(win);    task->state = FAILED;    task->d_time = time(0);    close(k);    return(1);  }  setkeepalive(k);  sk = addsock(k, gnum(1), S_R, initsend);  /* update task */  task->state = CONNECTING;  task->sk = sk;  /* connect task to socket */    sk->utask = task;    return(1);}/* 0xcc: got a download ack from the server. It is a string of the form: * <nick> <ip> <port> "<filename>" <md5> <linespeed> *   0      1     2        3          4       5       <-- token numbers */I_NAP_FUNC(sget){  download_t *task;  int rport;  int r, k;  sock_t *sk;  /* find matching REQUESTED or RRQUEUED item in the download list */  list_find(task, down, !strcasecmp(task->nick, tok[0]) && !strcasecmp(task->rfn, tok[3]) && (task->state == REQUESTED || task->state == RRQUEUED));  if (!task)  /* we received an ack for an item we had not requested. */    return(1);  /* ignore it silently. */    rport = atoi(tok[2]);    if (!rport && !info.port)  {    wp(win, "%s* Unable to get \"%s\" from %s because both parties are " \        "firewalled%s\n", RED, task->fn, task->nick, WHITE);    drw(win);    task->state = FAILED;    task->d_time = time(0);    return(1);  }  task->check = strdup(tok[4]);  task->linespeed = atoi(tok[5]);  task->addr.sin_family = AF_INET;  task->addr.sin_port = htons(rport);  task->addr.sin_addr.s_addr = htonl(swapl(strtoul(tok[1], 0, 10)));  if (!rport)   /* firewalled client, send push request and go WAITING */  {    sendpack(s, NAP_DSF, "%s \"%s\"", tok[0], tok[3]);    task->state = WAITING;    return(1);  }  /* else connect to the remote client and go CONNECTING */  /* sendpack(s, NAP_SX, "%s", tok[0]); */ /* why send a link speed query? */  k = socket(AF_INET, SOCK_STREAM, 0);      /* make socket non-blocking, so that connect will return immediately */  fcntl(k, F_SETFL, O_NONBLOCK);    r = connect(k, (struct sockaddr *)&task->addr, sizeof(task->addr));  if (r == -1 && errno != EINPROGRESS) {    wp(win, ""RED"* Error getting file (%s) from %s: %s"WHITE"\n", task->fn, tok[0], strerror(errno));    drw(win);    free(task->check);    task->state = FAILED;    task->d_time = time(0);    close(k);    return(1);  }  setkeepalive(k);  if (task->state == RRQUEUED) {    wp(win, "* Getting \"%s\" from %s\n", task->fn, task->nick);    drw(win);  }  sk = addsock(k, gnum(0), S_R, initget);    sk->dtask = task;  task->sk = sk;  task->state = CONNECTING;    return(1);}/* 209 (0xd1) <user> <speed>: user signon [SERVER]. server is   notifying client that a user in their hotlist, <user>, has signed   on the server with link <speed> */I_NAP_FUNC(suon){  hotlist_t *elt;    list_find(elt, hlist, !strcmp(elt->nm, tok[0]));  if (elt)  {    elt->conn = atoi(tok[1]);    elt->on = 1;    wp(win, "%s* %s (%s) is on napster%s\n", BRIGHT(GREEN), tok[0], conns[atoi(tok[1])], WHITE);    drw(win);  }    return(1);}/* 210 (0xd2) <user>: user signoff [SERVER]. server is notifying   client that a user on their hotlist, <user>, has signed off the   server.   this message is also sent by the server when the client attempts to   browse a nonexistent client.  [why don't they just use 404 for   this? -ed]*/I_NAP_FUNC(suoff){  hotlist_t *elt;  list_find(elt, hlist, !strcmp(elt->nm, tok[0]));    if (elt && elt->on)  {    elt->on = 0;    wp(win, "%s* %s has left napster%s\n", GREEN, tok[0], WHITE);    drw(win);  }    return(1);}/* 201 (0xc9) search response: * "<filename>" <md5> <size> <bitrate> <frequency> <length> <nick> <ip> *  <link-type> [weight] */I_NAP_FUNC(ssret){  ssearch_t *elt;  char *t;    if (num < 9)    return(1);    /* calculate short filename */  t = ud_basename(tok[0]);    /* create a new search list element */  elt = (ssearch_t *)malloc(sizeof(ssearch_t));    elt->song = strdup(quote(t));  elt->rfn = strdup(tok[0]);  elt->sz = atoi(tok[2]);  elt->brate = atoi(tok[3]);  elt->freq = atoi(tok[4]);  elt->time = atoi(tok[5]);  elt->nick = strdup(tok[6]);  elt->nip = htonl(swapl(strtoul(tok[7], (char **)NULL, 10)));  elt->conn = atoi(tok[8]);  if (elt->conn > 10 || elt->conn < 0)    elt->conn = 0;  elt->ping = -3;  elt->next = NULL;    /* and add it to the list. Note that it is faster to order the list     at the end, rather than keeping it ordered here. */  list_prepend(search, elt);  return(1);}/* 202 (0xca) end of search response from server */I_NAP_FUNC(ssend){  ssearch_t *cur, *cur1;  sock_t *sk;  int pin[2], pout[2], perr[2];  FILE *fin;  struct in_addr addr;  char *args[2];  char *napping;  int i;  list_length(ssearch_t, search, i);  wp(win, "* Received %d search %s\n", i, i==1 ? "result" : "results");  drw(win);  /* the easy case is if we can skip sending out pings. */  if (noping || !search) {    showresults(win, 1);    return(1);  }  /* attempt to run "napping" application, which will collect ping     information for us. */    /* first create pipes to and from */  /* do we need to do anything to avoid file descriptors 0-2? */  if (pipe(pin) < 0 || pipe(pout) < 0 || pipe(perr) < 0) {    wp(win, "* Could not collect ping results. pipe: %s\n", strerror(errno));    drw(win);    showresults(win, 1);    return(1);  }  switch(fork()) {  case -1: /* error */    wp(win, "* Could not collect ping results. fork: %s\n", strerror(errno));    drw(win);    showresults(win, 1);    return(1);    break;  case 0: /* child */    /* attach pipes to stdin, stdout, stderr */    close(pin[1]);    close(pout[0]);    close(perr[0]);    dup2(pin[0], 0);    dup2(pout[1], 1);    dup2(perr[1], 2);    close(pin[0]);    close(pout[1]);    close(perr[1]);    napping = getval("napping");    if (!napping)      napping = NAPPING;    args[0] = napping;    args[1] = NULL;    execvp(napping, args);    /* execlp only returns if there is an error. */    if (errno == ENOENT && getval("napping")==NULL) {      /* if napping was neither found nor explicitly requested, just	 ignore it silently and proceed without pings */      exit(1);    } else if (errno == EACCES) {      fprintf(stderr, "%s is not executable\n", napping);      exit(1);    } else {      fprintf(stderr, "%s: %s\n", napping, strerror(errno));      exit(1);    }    break;  default: /* parent */    close(pin[0]);    close(pout[1]);    close(perr[1]);    fin = fdopen(pin[1], "w");        /* send the IP addresses to napping */    for (cur=search; cur; cur=cur->next) {      if (cur->ping == -2)	continue;            addr.s_addr = cur->nip;       fprintf(fin, "%s\n", inet_ntoa(addr));                  for (cur1=search;cur1;cur1=cur1->next)	if (cur1->nip == cur->nip)	  cur1->ping = -2;    }    fprintf(fin, "\n");    fclose(fin);        /* hook up sockets to receive ping results */    addsock(pout[0], "icmp", S_R, icmpin);    addsock(perr[0], "icmperr", S_R, icmperr);    sk = findsock("icmp");    sk->f = fdopen(dup(pout[0]), "r");    sk = findsock("icmperr");    sk->f = fdopen(dup(perr[0]), "r");    /* set timer for 3 seconds */    /* timer is not currently used, since napping, if installed, times       out after 3 seconds anyway. */    /*        desc = strdup("[waiting for ping responses]");       addtimer(3, timed_pingresults, (void *)NULL, desc);    */    return (1);  }}/* timer is not currently used, since napping, if installed, times   out after 3 seconds anyway. */void timed_pingresults(void *dummy) {  sock_t *sk;  sk = findsock("icmp");  if (sk) {    fclose(sk->f);    delsock(sk->fd);  }  sk = findsock("icmperr");  if (sk) {    fclose(sk->f);    delsock(sk->fd);  }  showresults(wchan, 2);}/* diplay search results, either on the main screen or on the result   screen. LEVEL is 0 for browse, 1 for regular search, and 2 for   search with pings. */void showresults(WINDOW *win, int level) {  int min, sec, i;  float mb;  ssearch_t *a, *b, *cur;    /* sort the list, by ping times if we have them, else connection     speed, or by filename if this is a browse. A ping time of -1 is     considered "infinitely large" */  switch (level) {  case 2: /* display pings and connection speed, sort by pings first */    list_mergesort(ssearch_t, search, a, b, 		   (a->ping == b->ping && a->conn >= b->conn) ||		   (a->ping != -1 && (b->ping == -1 || a->ping < b->ping)));    break;  case 1: /* no pings; sort by connection speed */    list_mergesort(ssearch_t, search, a, b, a->conn >= b->conn);    break;  case 0: default: /* browse; sort by filename */    list_mergesort(ssearch_t, search, a, b, strcmp(a->song, b->song) <= 0);    break;  }  srch = 0;    /* show search result on main screen or result screen, depending     on whether "noresultscreen" was selected. */  if (nvar_default("noresultscreen", 0))   {    if (!search) {      return;    }    wp(win, ""BOLD"#"WHITE" | "BOLD"Song"WHITE" | Bitrate | Frequency | "BOLD"Length"WHITE" | "BOLD"Size"WHITE" | User%s%s\n", level>=1 ? " | "BOLD"Speed"WHITE"" : "" , level>=2 ? " | Ping" : "");    wp(win, "-----------------------------------------------------%s%s\n", level>=1 ? "--------" : "", level>=2 ? "-------" : "");    i=1;    list_forall (cur, search) {      min = cur->time/60;      sec = cur->time%60;      mb = ((float)cur->sz)/1048576.0;            wp(win, ""BOLD"%i. %s"WHITE" %ibps %ihz "BOLD"%i:%02i %.02fmb"WHITE" %s", i, (fl)?cur->rfn:cur->song, cur->brate, cur->freq, min, sec, mb, cur->nick);      if (level>=1) {	wp(win, " "BOLD"%s"WHITE"", conns[cur->conn]);      }      if (level>=2 && cur->ping == -1)	wp(win, " N/A");      else if (level>=2)	wp(win, " %i", cur->ping);      wp(win, "\n");      i++;    }    drw(win);  }  else   {    if (search) {      resetsscr();      switchtoscreen(RESULT_SCREEN);    }    plist();  }}      /* received a browse response from server: * <nick> "<filename>" <md5> <size> <bitrate> <frequency> <time>  *   0        1          2     3       4          5         6    */I_NAP_FUNC(srbrowse){  ssearch_t *cur, *cur1;  char *t;    if (num < 7)    return(1);    if (search == NULL)  {    search = (ssearch_t *)malloc(sizeof(ssearch_t));    cur = search;  }  else  {    for (cur1=NULL,cur=search;cur!=NULL;cur=cur->next)      cur1 = cur;    cur = (ssearch_t *)malloc(sizeof(ssearch_t));    cur1->next = cur;  }  

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -