"Fossies" - the Fresh Open Source Software Archive

Member "netbiff-0.9.18/proto.c" (21 Sep 2003, 5429 Bytes) of package /linux/privat/old/netbiff-0.9.18.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file.

    1 #include "proto.h"
    2 #include "buffer.h"
    3 #include "connection.h"
    4 #include "xlib.h"
    5 #include "gui.h"
    6 #include "conf.h"
    7 
    8 #include <stdlib.h>
    9 #include <string.h>
   10 #include <time.h>
   11 
   12 static void proto_init_conn(Connection *c) {
   13   xerror("%s: Initializing connection", c->name);
   14   if(xpopen2(c->command, &c->fd_in, &c->fd_out) < 0)
   15     return;
   16   c->state = CSTATE_WAIT_HELLO;
   17   gui.add_fd(c, GUI_FD_READ);
   18 }
   19 
   20 static void proto_poll_conn(Connection *c) {
   21   static const char pmsg[] = "POLL\n";
   22   buffer_put(&c->bout, pmsg, sizeof(pmsg) - 1);
   23   gui.add_fd(c, GUI_FD_WRITE);
   24   c->pending_commands++;
   25 }
   26 
   27 static void proto_add_next_folder(Connection *c) {
   28   static const char fmsg[] = "FOLDER ";
   29   const char *f;
   30 
   31   if(c->folders_added == c->nfolders) {
   32     c->state = CSTATE_NORMAL;
   33     proto_poll_conn(c);
   34     return;
   35   }
   36 
   37   f = c->folders[c->folders_added].name;
   38   xerror("%s: Adding folder %s", c->name, f);
   39   buffer_put(&c->bout, fmsg, sizeof(fmsg) - 1);
   40   buffer_put(&c->bout, f, strlen(f));
   41   buffer_put(&c->bout, "\n", 1);
   42   gui.add_fd(c, GUI_FD_WRITE);
   43 }
   44 
   45 static void proto_process_untagged(Connection *c, char *s) {
   46   char *resp[2];
   47   int nresp;
   48 
   49   nresp = xsplit(" ", s, resp, 2);
   50   if(!strcasecmp(resp[0], "UPDATE")) {
   51     if(!resp[1])
   52       return;
   53     connection_do_update(c, resp[1]);
   54   }
   55   else if(!strcasecmp(resp[0], "RESET")) {
   56     if(!resp[1])
   57         return;
   58     connection_do_reset(c, resp[1]);
   59   }
   60   else if(!strcasecmp(resp[0], "DATAREQUEST")) {
   61     char *args[2];
   62     int nargs;
   63     char *data;
   64     static const char respmsg[] = "DATARESPONSE ";
   65 
   66     /* ignore datarequests unless we're out of the "initial" states */
   67     if(c->state != CSTATE_NORMAL)
   68       return;
   69 
   70     if(!resp[1])
   71       return;
   72     nargs = xsplit(" ", resp[1], args, 2);
   73     if(nargs < 2)
   74       return;
   75 
   76     data = conf_read_data(c->name, args[0]);
   77     if(!data)
   78       data = gui.request_data(args[1], 1);
   79     if(!data)
   80       return;
   81 
   82     buffer_put(&c->bout, respmsg, sizeof(respmsg)-1);
   83     buffer_put(&c->bout, args[0], strlen(args[0]));
   84     buffer_put(&c->bout, " ", 1);
   85     buffer_put(&c->bout, data, strlen(data));
   86     buffer_put(&c->bout, "\n", 1);
   87 
   88     free(data);
   89     
   90     gui.add_fd(c, GUI_FD_WRITE);
   91     c->pending_commands++;
   92   }
   93 }
   94 
   95 static void proto_process_line(Connection *c, char *s) {
   96   char *resp[2];
   97   int nresp;
   98 
   99   xchomp(s);
  100   if(!*s)
  101     return;
  102   nresp = xsplit(" ", s, resp, 2);
  103 
  104   if(!strcasecmp(resp[0], "OK")) {
  105     switch(c->state) {
  106       case CSTATE_WAIT_HELLO:
  107         c->penalty = 1;
  108         c->state = CSTATE_ADDING_FOLDERS;
  109         proto_add_next_folder(c);
  110         break;
  111       case CSTATE_ADDING_FOLDERS:
  112         c->folders_added++;
  113         proto_add_next_folder(c);
  114         break;
  115       case CSTATE_NORMAL:
  116         if(c->pending_commands > 0)
  117           c->pending_commands--;
  118         else
  119           xerror("%s: unexpected OK response", c->name);
  120         break;
  121     }
  122   }
  123 
  124   else if(!strcasecmp(resp[0], "NO")) {
  125     xerror("%s: %s", c->name, resp[1] ? resp[1] : "Unknown Error");
  126     switch(c->state) {
  127       case CSTATE_WAIT_HELLO:
  128         connection_close(c);
  129         break;
  130       case CSTATE_ADDING_FOLDERS:
  131         connection_close(c);
  132         break;
  133       case CSTATE_NORMAL:
  134         if(c->pending_commands > 0)
  135           c->pending_commands--;
  136         else
  137           xerror("%s: unexpected NO response", c->name);
  138         break;
  139     }
  140   }
  141 
  142   else if(!strcasecmp(resp[0], "BAD")) {
  143     xerror("%s reports protocol error from our end: %s", 
  144         c->name, 
  145         resp[1] ? resp[1] : "Unknown Error");
  146     connection_close(c);
  147   }
  148 
  149   else if(!strcasecmp(resp[0], "*")) {
  150     if(nresp > 1) 
  151       proto_process_untagged(c, resp[1]);
  152   }
  153 
  154   else {
  155     xerror("%s sent us gibberish: %s", c->name, resp[0]);
  156     connection_close(c);
  157   }
  158 }
  159 
  160 void proto_do_conn_input(Connection *c) {
  161   char buf[4096];
  162   int result;
  163   char *p;
  164 
  165   result = read(c->fd_in, buf, sizeof(buf));
  166   if(result < 0) {
  167     xerror("%s: read error: %s", c->name, xsyserr());
  168     connection_close(c);
  169     return;
  170   }
  171   else if(result == 0) {
  172     xerror("%s: Hangup Detected", c->name);
  173     connection_close(c);
  174     return;
  175   }
  176   buffer_put(&c->bin, buf, result);
  177 
  178   while((p = buffer_get_line(&c->bin))) {
  179     proto_process_line(c, p);
  180     free(p);
  181   }
  182 }
  183 
  184 void proto_do_conn_output(Connection *c) {
  185   char *p;
  186   int len;
  187 
  188   len = buffer_get(&c->bout, &p);
  189   if(len) {
  190     int result;
  191     result = write(c->fd_out, p, len);
  192     if(result < 0) {
  193       xerror("%s: write: %s", c->name, xsyserr);
  194       connection_close(c);
  195     }
  196     else if(result < len) 
  197       buffer_put(&c->bout, p + result, len - result);
  198     free(p);
  199   }
  200   if(!buffer_has_data(&c->bout))
  201     gui.delete_fd(c, GUI_FD_WRITE);
  202 }
  203 
  204 void proto_do_io(fd_set *rfds, fd_set *wfds) {
  205   int i;
  206 
  207   for(i = 0; i < nconnections; i++) {
  208     if(FD_ISSET(connections[i].fd_in, rfds))
  209       proto_do_conn_input(connections+i);
  210     if(FD_ISSET(connections[i].fd_out, wfds))
  211       proto_do_conn_output(connections+i);
  212   }
  213 }
  214 
  215 void proto_do_poll() {
  216   int i;
  217 
  218   for(i = 0; i < nconnections; i++)
  219     if(connections[i].state == CSTATE_NORMAL 
  220         && !connections[i].pending_commands)
  221       proto_poll_conn(connections+i);
  222 }
  223 
  224 void proto_do_retries() {
  225   int i;
  226   time_t now;
  227 
  228   now = time(0);
  229 
  230   for(i = 0; i < nconnections; i++) {
  231     if(connections[i].state == CSTATE_PENALTY_BOX) {
  232       if(connections[i].retry_time <= now) {
  233         proto_init_conn(connections+i);
  234       }
  235     }
  236   }
  237 }