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

📄 event.c

📁 P2P NAP的C实现 P2P在网络应用中越来越流行
💻 C
📖 第 1 页 / 共 3 页
字号:
/* Copyright (c) 2000  Kevin Sullivan <nite@gis.net> * * Please refer to the COPYRIGHT file for more information. *//* This file contains functions that are used to handle socket events.   The scheduler for these events (main loop) is in scheck.c. */#ifdef HAVE_CONFIG_H# include <config.h>#endif#include <string.h>#include <errno.h>#include <sys/types.h>#include <sys/socket.h>#include <stdlib.h>#include <ctype.h>#include <time.h>#include <ncurses.h>#include "alias.h"#include "codes.h"#include "colors.h"#include "defines.h"#include "event.h"#include "scheck.h"#include "nap.h"#include "sscr.h"#include "cmds.h"#include "scmds.h"#include "timer.h"#include "winio.h"#include "lists.h"#ifdef MEMWATCH  #include "memwatch.h"#endifextern upload_t *up;extern download_t *down;extern info_t info; extern int srch; /* 1 while search or browse is in progress */extern struct inbrowse_s directbrowse; int noprint=0;/* not used */void initssock(int port){  struct sockaddr_in frm;  int s, on = 1;    s = socket(AF_INET, SOCK_DGRAM, 0);    frm.sin_addr.s_addr = INADDR_ANY;  frm.sin_port = htons(port);  frm.sin_family = AF_INET;    setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));  setkeepalive(s);    bind(s, (struct sockaddr *)&frm, sizeof(frm));    addsock(s, "ssock", S_R, inssock);}/* not used */int inssock(WINDOW *win, sock_t *m){  char buf[1024];  /* note: don't need malloc */  struct sockaddr_in frm;  int frmlen = sizeof(frm);    memset(buf, 0, 1024);    recvfrom(m->fd, buf, 1024, 0, (struct sockaddr *)&frm, &frmlen);  if (!strncmp(buf, "VERSION", strlen("VERSION")))  {    if (strcmp(strchr(buf, ' ')+1, VERSION))    {      wp(win, "%s* Attention: Version %s of nap is out!%s\n", BRIGHT(BLUE), strchr(buf, ' ')+1, WHITE);      wp(win, "%s* Attention: Please visit http://www.gis.net/~nite/ to upgrade immediately%s\n", BRIGHT(BLUE), WHITE);      drw(win);    }  }  else if (!strncmp(buf, "MSG", strlen("MSG")))  {    wp(win, "%s* %s%s\n", BRIGHT(BLUE), strchr(buf, ' ')+1, WHITE);    drw(win);  }    return(1);}/* "ipc" stands for "inter process communication". This is simply a * pipeline, created at the beginning of main(). It is used by child * processes to send output to the main screen. For instance, when * doing time-consuming things such as rebuilding the library, we fork * a child, but the child must then be able to send output to the main * screen. Using wp() directly won't work, both because the output * would be asynchronous, and because the child can't update the * parents' data structures. * * The reading end of the connection is here, and simply prints any * received data to the main screen. The sending happens in the many * calls in cmds.c of the form * *   ssock(ipcs[1], "* Successfully rebuilt your library\n");  *//* receive on ipc socket */int inipc(WINDOW *win, sock_t *m){  int s = m->fd;  char *buf;    rsock(s, &buf);  if (!buf)    return(1);    /* addscroll(win, buf);     dscr(win); */  wp(win, buf);  /* use wp so the output goes to the log file also */  drw(win);    free(buf);    return(1);}/* receive from server socket */int inserv(WINDOW *win, sock_t *m){  int s = m->fd, j, n, r;  phead_t *pk;  char *data;    r = recvpack(s, &data, &pk);  if (r == -2)    return(1);  else if (r == -1) {    wp(win, ""RED"* Error: %s"WHITE"\n", strerror(errno));    drw(win);    delsock(m->fd);    return(1);  } else if (r == -3) {    wp(win, ""RED"* Error: unexpected end of file from server"WHITE"\n");    drw(win);    delsock(m->fd);    return(1);  }  for (j=0;data[j];j++)    if (data[j] == 10)    {      strncpy(data+j, data+j+1, strlen(data+j+1));      data[strlen(data)-1] = 0;    }      n = parsein(s, pk->op, data, win);  noprint = 0;  if (n == -1) {    delsock(m->fd);    return(1);  }  else if (n == -2)    return(-1);      /* don't know what this does, or used to			do. Don't know of a concrete situation where			parsein returns -2, or in fact -1. */    free(pk);  free(data);    dstatus();  return(1);}/* a remote client has connected to our data port; we just accept the   connection and then listen on the dedicated port for that connection */int gconn(WINDOW *win, sock_t *m){  int s = m->fd, r;  struct sockaddr_in frm;  int frmlen = sizeof(frm);    r = accept(s, (struct sockaddr *)&frm, &frmlen);  if (r == -1)    return(1);    setkeepalive(s);  addsock(r, "conn", S_R, lsock);  ssock(r, "1");    return(1);}/* a remote client has connected to us and is about to say "GET", "SEND", * "GETLIST", or "SENDLIST" (the latter two are for direct browsing) */int lsock(WINDOW *win, sock_t *m){  char buf[8];  int r;  memset(buf, 0, sizeof(buf));  r = recv(m->fd, &buf, sizeof(buf), MSG_PEEK);  if (r==-1)  {    wp(win, ""RED"* Bogus connection from remote client (%s): %s"WHITE"\n", getpeerip(m->fd), strerror(errno));    drw(win);    delsock(m->fd);    return(1);  }  /* GET and SEND are prefixes of GETLIST and SENDLIST respectively,   * so have to check for the longer words first */  if (!strncmp(buf, "GETLIST", 7))  {    recv(m->fd, &buf, 7, 0);    m->func = dogetlist;    m->t = S_W; /* prepare to write */  }  else if (!strncmp(buf, "SENDLIST", 8))  {    recv(m->fd, &buf, 8, 0);    /* we rename the connection here so that we can find it and delete it     * if the direct browse request times out. This is necessary because     * a broken client like Napster v2.0 BETA 9.6 will send a SENDLIST and     * nothing else. As a result, dosendlist will never be called, and the      * socket will remain open until the program quits. */    free(m->socknm);    m->socknm = strdup("sendlist");    m->func = dosendlist;  }  else              /* note: trailing "else" goes with following "if"!! */  if (!strncmp(buf, "GET", 3))  {    recv(m->fd, &buf, 3, 0);    m->func = doget;  }  else if (!strncmp(buf, "SEND", 4))  {    recv(m->fd, &buf, 4, 0);    m->func = dosend;  }  else  {    char *data=NULL;    /* see what the peer was saying */    r = rsock(m->fd, &data);    wp(win, ""RED"* Bogus connection from remote client (%s) [%s]"WHITE"\n", getpeerip(m->fd), data ? quote(data) : "");    drw(win);    ssock(m->fd, "INVALID REQUEST\n");    free(data);    delsock(m->fd);    return(1);  }      return(1);}/* remote client connected to our data port and issued a GET command */int doget(WINDOW *win, sock_t *m){  char *buf, *nick, *rfn;  size_t bsz;  upload_t *task;  struct stat st;  sock_t *sv;  char **tok;  int i, cnt;  FILE *f;    if (rsock(m->fd, &buf) == -1) {    delsock(m->fd);    return(1);  }      tok = form_tokso(buf, &cnt);   /* we should be able to use form_tokso() here instead of the more general   * form_toks() */    /* the client should have sent a string of the form   * <remotenick> "<filename>" <offset> */  if (cnt < 3)  {    wp(win, ""RED"* Bogus GET command from remote client (%s) [GET%s]"WHITE"\n", getpeerip(m->fd), quote(buf));    drw(win);    ssock(m->fd, "INVALID REQUEST\n");    free(buf);    for (i=0;i<cnt;i++)      free(tok[i]);    free(tok);    delsock(m->fd);    return(1);  }    nick = strdup(tok[0]);  rfn = strdup(tok[1]);  bsz = strtoul(tok[2], 0, 10);  free(buf);    for (i=0;i<cnt;i++)    free(tok[i]);  free(tok);    list_find(task, up, !strcasecmp(task->nick, nick) && !strcasecmp(task->rfn, rfn) && task->state==WAITING);  if (!task)  {    /* the following error message is often a result of an upload request       which we rejected, but we sent an accept message to the server. It       is more likely to be confusing than useful to the user, so we        omit it. */    /* wp(win, "%s* %s requested upload of \"%s\" but it isn't in the upload list! (GET)%s\n", RED, nick, rfn, WHITE);       drw(win); */    ssock(m->fd, "INVALID REQUEST\n");    free(nick);    free(rfn);    delsock(m->fd);    return(1);  }    free(nick);  free(rfn);  /* otherwise accept the request. */  /* 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);    ssock(m->fd, "FILE NOT FOUND\n");    task->state = FAILED;    task->d_time = time(0);    delsock(m->fd);    return(1);  }    /* determine file size */  fstat(fileno(f), &st);  if (bsz > st.st_size)  /* note: bsz is unsigned, thus bsz<0 impossible */  {    wp(win, ""RED"* Error sending file \"%s\" to %s: illegal offset requested (%lu/%lu)"WHITE"\n", task->fn, task->nick, (long)bsz, (long)st.st_size);    drw(win);    ssock(m->fd, "INVALID REQUEST\n");    fclose(f);    task->state = FAILED;    task->d_time = time(0);    delsock(m->fd);    return(1);  }    fseek(f, bsz, SEEK_SET);     /* go to state IN_PROGRESS */    task->sk = m;  task->f = f;  task->size = st.st_size;  task->bsz = bsz;  task->pos = bsz;  task->p_time = time(0);  task->state = IN_PROGRESS;  /* link task to socket */  m->utask = task;  m->bwlimit = 1;  bandwidth_init(&m->bw);  m->func = sfile;  m->t = S_W;  free(m->socknm);  m->socknm = strdup(gnum(1));    sv = findsock("server");  if (sv)    sendpack(sv->fd, NAP_UP, NULL);    /* send the file size */  ssock(m->fd, "%lu", (long)task->size);    wp(win, "* Sending file \"%s\" to %s (%lu bytes)\n", task->fn, task->nick, (long)task->size);  drw(win);    return(1);}/* we requested a file from a firewalled client. The remote client has * connected to us and is about to start uploading the file */int dosend(WINDOW *win, sock_t *m){  char *buf, *nm, *rfn, *fn, *lfn;  FILE *f;  size_t size;  download_t *task;  sock_t *sv;  char **tok;  int i, r, cnt;    if (rsock(m->fd, &buf) == -1)  {    delsock(m->fd);    return(1);  }  tok = form_tokso(buf, &cnt);    /* the remote client should have sent a string of the form    * <remotenick> "<filename>" <size> */  if (cnt < 3)  {    wp(win, ""RED"* Bogus SEND command from remote client (%s) [SEND%s]"WHITE"\n", getpeerip(m->fd), quote(buf));    drw(win);    ssock(m->fd, "INVALID REQUEST\n");    free(buf);    for (i=0;i<cnt;i++)      free(tok[i]);    free(tok);    delsock(m->fd);    return(1);  }    nm = strdup(tok[0]);  rfn = strdup(tok[1]);  size = strtoul(tok[2], 0, 10);  free(buf);    for (i=0;i<cnt;i++)    free(tok[i]);  free(tok);  /* can remote client send "INVALID REQUEST" after a "SEND" ? */  if (!strcasecmp(nm, "FILE")) /* "FILE NOT SHARED" or "FILE NOT FOUND" */  {    wp(win, "%s* Error downloading from firewalled remote client " \        "[FILE NOT SHARED]%s\n", RED, WHITE);    drw(win);    /* the download this error message corresponds to will be removed       from the download list when the item's timer times out - we       can't do much better since we don't know the nick+filename yet       (and going by IP address would be unreliable) */    free(nm);    free(rfn);    delsock(m->fd);    return(1);  }

⌨️ 快捷键说明

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