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

📄 nap.c

📁 P2P NAP的C实现 P2P在网络应用中越来越流行
💻 C
📖 第 1 页 / 共 4 页
字号:
    wp(wchan, "Error: Invalid username\n");    drw(wchan);    free(t1);    free(rcv);    return(-1);  }  else if (rcv->op == NAP_UNOK) {    wp(wchan, "Registered username\n");    drw(wchan);  }  else  {    wp(wchan, "Unknown op: 0x%x\n", rcv->op);    drw(wchan);    free(t1);    free(rcv);    return(-1);  }    free(t1);  free(rcv);  t1 = NULL;    r = sendpack(s, NAP_REG, "%s %s %i \"%s\" %i %s", user, pass, data, identity ? identity : IDENTITY, conn, email);  if (r<0) {    wp(wchan, "Error: %s\n", strerror(errno));    drw(wchan);    return(-1);  }  r = recvpack_t(s, &t1, &rcv, timeout);  while (r == -2) {    r = recvpack_t(s, &t1, &rcv, timeout);  }  if (r == -1) {    wp(wchan, "Error while receiving data: %s\n", strerror(errno));    drw(wchan);    return(-1);  } else if (r == -3) {    wp(wchan, "Error: unexpected end of file from server\n");    drw(wchan);    return(-1);  } else if (r == -4) {    wp(wchan, "Error: Connection timed out\n");    drw(wchan);    return(-1);  }    if (rcv->op == NAP_LOGERROR)  {    wp(wchan, "Error: %s\n", t1);    drw(wchan);    free(t1);    free(rcv);    return(-1);  }    /* the following works for opennap and slavanap. The "email address"     they send is of the form anon@servername. Slavanap also sends an     additional integer. */  if (strncmp(t1, "anon@", 5)==0) {    char *p = strchr(t1, ' ');    if (p) {      *p = 0;    }    wp(wchan, "Server's name appears to be %s\n", t1+5);    drw(wchan);  }  free(t1);  free(rcv);    return r;}/* calculate the name of the hotlist file */char *glistn(char *t){  char *r1 = NULL;  char *r2;    msprintf(&r1, HOTLISTFILE, t);  r2 = home_file(r1);  free(r1);  return(r2);}/* send initial hotlist during the login process */void checkhotlist(int s, char *fn){  FILE *f;  char *rd;  hotlist_t *elt;    /* first delete old hlist, if any */  list_forall_unlink(elt, hlist) {    free(elt->nm);    free(elt);  }  f = fopen(fn, "r");  if (!f)    return;    while ((rd = nap_getline(f)) != NULL)  {    if (!strlen(rd)) {      free(rd);      break;    }    /* create new hotlist entry */    elt = (hotlist_t *)malloc(sizeof(hotlist_t));    elt->nm = rd;    elt->conn = 0;    elt->on = 0;    /* add it to the list */    list_append(hotlist_t, hlist, elt);    /* and register it with server */    sendpack(s, NOTIFY_CHECK, "%s", rd);  }  fclose(f);}/* Get news on the client. Write it to the given fd. Used by the   command /news, or on startup. This simply looks at a specific web   page which is assumed to have such news. Forward compatibility is   important here, thus every line of that page starts with a keyword,   and we ignore lines whose keyword we don't know. Note: this   function may be executed in a child process, since it does not   update any state. Return 1 if there was news, 0 if there was none,   and -1 on error. Return 2 if there was news, but serial!=NULL and   we have seen these very news before. In case of -1, the variable   *errmsg is set to a (static) error message. If fd is 1, do some   special formatting, write in black and white, and send the output   through wp() for the log file's benefit. If we return 1 (there is   new news) and serial!=NULL and the news had a serial identifier,   that identifier is returned in *serial. */int checknv(int fd, int timeout, const char **errmsg, char **serial){  FILE *f, *nfile;  int relevant, news, oldnews;  char *b, *c;  char *nfilename;  if (serial) {    *serial = NULL;  }  f = open_url(NEWSURL, timeout, errmsg);  if (!f) {    return -1;  }  relevant = 0;  news = 0;  oldnews = 0;    /* parse each line of the file */  while ((b = nap_getline(f)) != NULL) {    if (*b == 0 || !strncmp(b, "#", 1)) { /* skip comments and blank lines */      free(b);      continue;    }    if (serial && !strncmp(b, "SERIAL ", 7)) {      /* check to see if this version of the news is old */      nfilename = home_file(OLDNEWSFILE);      nfile = fopen(nfilename, "r");      free(nfilename);      if (nfile) {	c = nap_getline(nfile);	fclose(nfile);	if (c && !strcmp(b+7, c)) {	  oldnews = 1;	}	if (c) {	  free(c);	}      }      if (*serial) {	free(*serial);      }      *serial = strdup(b+7);      free(b);      continue;    }    if (!strncmp(b, "VERSION ", 8) && !strcmp(b+8, VERSION)) {      relevant = 1;      /* news for this client */      free(b);      continue;    }    if (!strncmp(b, "OTHER ", 6) || !strcmp(b, "OTHER")) {      relevant = 1;      free(b);      continue;    }    if (relevant && (!strcmp(b, "END") || !strncmp(b, "END ", 4))) {      free(b);      break;    }    if (relevant && !strncmp(b, "ECHO ", 5)) {      if (news==0 && fd==1) {	wp(NULL, "\n**********************************************************************\n");	wp(NULL, "NEWS:\n");      }      if (fd==1) {	wp(NULL, "%s\n", b+5);      } else {	ssock(fd, ""MAGENTA"* %s"WHITE"\n", b+5);      }      news = 1;      free(b);      continue;    }    free(b);  }  if (news && fd==1) {    wp(NULL, "**********************************************************************\n\n");  }  fclose(f);  if (news && !oldnews) {    return 1;  }  if (serial && *serial) {    free(*serial);  }  if (news) {    return 2;  }  return 0;} /* save channels from channel list CL to file FN. Return -1 on i/o   error with errno set, else 0 */int savechans(chans_t *cl, char *fn){  chans_t *cur;  FILE *f;    f = fopen(fn, "w");  if (!f) {    return -1;  }  for (cur=cl;cur;cur=cur->next)    if (!cur->q)      fprintf(f, "%s\n", cur->nm);    fclose(f);  return 0;}/* load channels from file FN and join them. Return -1 on i/o error with   errno set, else 0. S is server's fd. */int loadchans(int s, char *fn){  char *line;  FILE *f;    f = fopen(fn, "r");  if (!f) {    return -1;  }  while (1)  {    line = nap_getline(f);    if (line == NULL) {      break;    }    if (*line != 0)      sendpack(s, NAP_JOIN, "%s", line);    free(line);  }    fclose(f);  return 0;}chans_t *findchan(chans_t *h, char *chan){  chans_t *cur;  list_find(cur, h, !strcasecmp(cur->nm, chan));  if (cur)    return cur;  if (chan[0]!='#') {    list_find(cur, h, cur->nm[0]=='#' && !strcasecmp(cur->nm+1, chan));  }  return(cur);}chans_t *findquery(chans_t *h, char *chan){  chans_t *cur;  for (cur=h;;cur=cur->next)  {    if (!cur)      return(NULL);    if (!strcasecmp(cur->nm, chan) && cur->q == 1)      return(cur);  }}/* for sending a packet to the napster server, whose file descriptor   is s. Return -1 on error (with errno set), or else the number of   bytes written. If s==-1, we print an error message and set errno to   EINVAL. */int sendpack(int s, int op, const char *fmt, ...){  char *data;  char *pack;  /* first four bytes of pack are header, remaining is data */  int len;  va_list args;  int r;    if (s == -1)  {    wp(wchan, "%s* Not connected to the server%s\n", RED, WHITE);    drw(wchan);    errno = EINVAL;    return(-1);  }    if (fmt) {    data = NULL;    va_start(args, fmt);    vasprintf(&data, fmt, args);    va_end(args);  } else {    data = strdup("");  }  len = strlen(data);  pack = (char *)malloc(len+5);  strcpy(pack+4, data);    /* len and op are sent as little-endian, 16-bit unsigned integers */  pack[0] = 0xff & len;  pack[1] = 0xff & (len>>8);  pack[2] = 0xff & op;  pack[3] = 0xff & (op>>8);    if (nvar("debug") == 2) {    wp(wchan, ""DARK GREEN"--> (0x%x=%d) <%s>"WHITE"\n", op, op, quote(pack+4));    drw(wchan);  }    r = send(s, pack, len+4, 0);  free(pack);  free(data);      return(r);}/* write formatted data to file descriptor, and possibly log debugging   info. Return the number of characters written, or -1 on error with   errno set. */int ssock(int s, const char *fmt, ...){  char *data;  va_list args;  int r;    data = NULL;  va_start(args, fmt);  vasprintf(&data, fmt, args);  va_end(args);    if (nvar("debug") == 2)  {    sock_t *sk = findsockfd(s);    wp(wchan, ""DARK GREEN"--> [to %d=%s] <%s>"WHITE"\n", s, sk ? sk->socknm : "?", quote(data));    drw(wchan);  }  r = write(s, data, strlen(data));    free(data);  return(r);}/* activate keepalive so we will know when the other side silently   disappears. (MVB) */int setkeepalive(int sock){  int on = 1;  return setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof(on));}/* receive a packet from the server (at file descriptor s). Return -1   if there was an error (with errno set), or -3 if there was an   unexpected end-of-file. Return -2 if only part of the packet could   be read; in this case, a subsequent call to recvpack will continue   to read the same packet. Return 1 on success */int recvpack(int s, char **buf, phead_t **hdr) {  return recvpack_t(s, buf, hdr, -1);}/* like recvpack, except it also has a timeout (in seconds). If t=-1,   no timeout. If t=0, return immediately if there is no data to read.   On timeout, return -4. */int recvpack_t(int s, char **buf, phead_t **hdr, int t){  int r, i;  fd_set fs;  struct timeval tv;  /* the following two static objects, if non-NULL, contain partial     information that was read at the previous call of recvpack */  static phead_t *thdr = NULL;  static unsigned char *tdbuf = NULL;  static int tpos;  /* how many characters in tdbuf */  /* if timeout requested, wait at most t seconds until data becomes     available for reading. */  if (t>=0) {    FD_ZERO(&fs);    FD_SET(s, &fs);    tv.tv_usec = 0;    tv.tv_sec = t;        r = select(s+1, &fs, NULL, NULL, &tv);    if (r==-1) {      return -1;    } else if (r==0) { /* timeout */      return -4;    }  }  if (!thdr)  {    unsigned char acc[4];      for (i=0; i<4; i+=r)     {      r = read(s, acc+i, 4-i);  /* note that this might hang */      if (r <= 0)      {        *hdr = NULL;        *buf = NULL;        return(r==0 ? -3 : -1);      }    }    thdr = (phead_t *)malloc(sizeof(phead_t));    /* little-endian, 16 bit unsigned integers */    thdr->len = acc[0] | (acc[1]<<8);    thdr->op  = acc[2] | (acc[3]<<8);  }    if (!thdr->len)  {    *hdr = thdr;    *buf = strdup("");    thdr = NULL;    /* print messages with length 0 */    if (nvar("debug") == 2) {      wp(wchan, ""DARK GREEN"<-- (0x%x=%d) <>"WHITE"\n", (*hdr)->op, (*hdr)->op);      drw(wchan);    }    return(1);  }    FD_ZERO(&fs);  FD_SET(s, &fs);  tv.tv_usec = 0;  tv.tv_sec = 0;    if (!select(s+1, &fs, NULL, NULL, &tv))    return(-2);    if (!tdbuf)  {    tdbuf = (char *)malloc(thdr->len+1);    memset(tdbuf, 0, thdr->len+1);    tpos = 0;  }    r = read(s, tdbuf+tpos, thdr->len-tpos);  if (r <= 0)  {    free(tdbuf);    free(thdr);    tdbuf = NULL;    thdr = NULL;    *buf = NULL;    *hdr = NULL;    return(r==0 ? -3 : -1);  }  if ((r+tpos) < thdr->len)  {    *buf = NULL;    *hdr = NULL;    tpos += r;    return(-2);  }    *buf = tdbuf;  *hdr = thdr;    tdbuf = NULL;  thdr = NULL;    if (nvar("debug") == 2)  {    wp(wchan, ""DARK GREEN"<-- (0x%x=%d) <%s>"WHITE"\n", (*hdr)->op, (*hdr)->op, quote(*buf));    drw(wchan);  }    return(1);}/* read at most 4096 bytes from the given file descriptor. Here, the   arbitrary limit (4096) is actually desirable, since we want to   avoid some talkative peer monopolizing our attention. */int rsock(int s, char **buf){  int r;  fd_set fs;  *buf = (char *)malloc(4096+1);    FD_ZERO(&fs);  FD_SET(s, &fs);    if (select(s+1, &fs, NULL, NULL, NULL) == -1)  {    free(*buf);    *buf = NULL;    return(-1);  }    if ((r = read(s, *buf, 4096)) <= 0)  {    free(*buf);    *buf = NULL;    return(-1);  }  (*buf)[r] = 0;  /* make sure it's 0 terminated */  *buf = (char *)realloc(*buf, r+1);  if (nvar("debug") == 2)  {    sock_t *sk = findsockfd(s);     wp(wchan, ""DARK GREEN"<-- [from %d=%s] <%s>"WHITE"\n", s, sk ? sk->socknm : "?", quote(*buf));    drw(wchan);  }    return(r);}

⌨️ 快捷键说明

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