"Fossies" - the Fresh Open Source Software Archive

Member "delegate9.9.13/src/thruwayd.c" (10 Sep 2009, 63815 Bytes) of package /linux/misc/old/delegate9.9.13.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. For more information about "thruwayd.c" see the Fossies "Dox" file reference documentation.

    1 /*////////////////////////////////////////////////////////////////////////
    2 Copyright (c) 1997-2000 Yutaka Sato and ETL,AIST,MITI
    3 Copyright (c) 2001-2006 National Institute of Advanced Industrial Science and Technology (AIST)
    4 AIST-Product-ID: 2000-ETL-198715-01, H14PRO-049, H15PRO-165, H18PRO-443
    5 
    6 Permission to use this material for noncommercial and/or evaluation
    7 purpose, copy this material for your own use, and distribute the copies
    8 via publicly accessible on-line media, without fee, is hereby granted
    9 provided that the above copyright notice and this permission notice
   10 appear in all copies.
   11 AIST MAKES NO REPRESENTATIONS ABOUT THE ACCURACY OR SUITABILITY OF THIS
   12 MATERIAL FOR ANY PURPOSE.  IT IS PROVIDED "AS IS", WITHOUT ANY EXPRESS
   13 OR IMPLIED WARRANTIES.
   14 //////////////////////////////////////////////////////////////////////////
   15 Content-Type:   program/C; charset=US-ASCII
   16 Program:    thruwayd.c (bundled-sockets server)
   17 Author:     Yutaka Sato <ysato@etl.go.jp>
   18 Description:
   19     Naming:
   20     - BSocks: bundled sockets
   21     - BillGates :-p
   22     - MTCP: Multiplexed Transport Control Protocol
   23     - ThruWay: ... as is ...
   24     - AlliGate: ALL-in-one application level Integrated Gateway ?
   25 History:
   26     971113  created
   27 //////////////////////////////////////////////////////////////////////#*/
   28 #include <ctype.h>
   29 #include <stdio.h>
   30 #include <stdlib.h>
   31 #include <signal.h>
   32 #include "ystring.h"
   33 #include "vsocket.h"
   34 #include "fpoll.h"
   35 #include "vaddr.h"
   36 #include "dglib.h"
   37 
   38 #define TW_PORT     8715
   39 #define TW_ENTR0    "ringer.etl.go.jp:8715"
   40 #define TW_EXIT0    "localhost:9080"
   41 #define TW_EXIT     0
   42 
   43 #define BSOCKS_VER  "0.9"
   44 /*
   45  *  ThruWay packet header
   46  */
   47 #define M_CTLTYPE   0
   48 #define M_CTLARG    1
   49 #define M_SENDER    2   /* sender port */
   50 #define M_RECEIVER  3   /* receiver port */
   51 #define M_PACKID    4
   52 #define M_PACKLENG  5
   53 #define M_PACKSIZE  6
   54 #define int32 int
   55 #define HEADSIZE (M_PACKSIZE*sizeof(int32))
   56 
   57 #include <errno.h>
   58 #ifndef EINPROGRESS
   59 #define EINPROGRESS -1
   60 #endif
   61 #ifndef EWOULDBLOCK
   62 #define EWOULDBLOCK -1
   63 #endif
   64 #ifndef EALREADY
   65 #define EALREADY    -1
   66 #endif
   67 
   68 /*
   69  *  BUNDLED-SOCKETS SERVER
   70  *  OMUNIBUS
   71  */
   72 typedef struct {
   73     int p_status;   /* current I/O status */
   74     int p_statussave;   /* I/O status saved on ST_WAIT_RFLUSH */
   75     int p_waitdst;  /* destination port (status is ST_WAIT_SEND) */
   76     int p_waitwcc;  /* waiting to be flushed (ST_WAIT_RFLUSH) */
   77     int p_bsize;    /* I/O buffer size */
   78     int p_rwcc;     /* current I/O position */
   79     int p_bleng;    /* buffered Output */
   80     int p_flagment; /* size of left flagment of current packet */
   81     defQStr(p_buff);    /* I/O buffer */
   82     int p_iocount;  /* total I/O count */
   83     int p_iototal;  /* total I/O bytes */
   84     int p_pkcount;  /* total packet I/O count */
   85     int p_pktotal;  /* total packet I/O bytes */
   86     int p_remotetotal;  /* total bytes finished on remote peer */
   87     int p_notifiedcc;   /* total bytes notified to remote peer */
   88     int p_pendingto;
   89     int p_pendingcc;
   90     int p_waitingcc;    /* packet size at WAIT_SEND status BSOCKS */
   91 } PORT;
   92 
   93 typedef struct {
   94     int p_portid;
   95   const char   *p_sockname; /* sockname of source (accepted) port */
   96   const char   *p_peername; /* peername of source (accepted) port */
   97     int p_lport;    /* my I/O port (socket's file descriptor) */
   98     int p_rport;    /* peer I/O port at remote router */
   99     int p_rbuff;    /* buffer size of the peer I/O port */
  100     int p_proto;    /* protocol with client */
  101     int p_resfail;  /* count of failures of DNS trial */
  102     int p_connecting;   /* connecting */
  103     int p_EOF;      /* got local EOF */
  104     int p_sentEOF;  /* local EOF is notified to the peer */
  105     int p_closing;  /* closing (OR of reasons) */
  106     int p_ctime;    /* creation time */
  107     int p_waitingQ; /* next waiting port */
  108 
  109     int p_connectingR;  /* connecting at remote router */
  110     int p_invoked;  /* remote peer port invoked */
  111     int p_connected;    /* remote peer connected to destination */
  112     MStr(   p_dsthost,256); /* ultimate destination host */
  113     int p_dstport;  /* ultimate destination port */
  114     int p_dstsock;  /* exit to peer port in this router */
  115     int p_srcsock;  /* entrance from peer port in this router */
  116 
  117     int p_accport;  /* doing ACCEPT from remote */
  118     int p_accsock;  /* bound peer port after acceptance */
  119                 /* first child vport in the accept queue */
  120     int p_acclast;  /* last child vport in the accept queue */
  121     int p_acceptQ;  /* next peer vport in the accept queue */
  122 
  123     MStr(   p_bhost,256);   /* router host */
  124     int p_bport;    /* router port */
  125 
  126     PORT    io[2]; /**/
  127 } IOPORT;
  128 
  129 typedef struct {
  130     int q_portx;
  131     int q_ports;
  132 } PORTS;
  133 
  134 #define MAXPORTS 4096
  135 
  136 typedef struct {
  137     FILE   *te_LOGFP;
  138     int te_logisatty;
  139     int te_prefetched;
  140     int te_PACKID;
  141     int te_dbglev;
  142     int te_CONN_PREFECH;
  143 
  144     int te_NUMPORTS;
  145     IOPORT **te_ports;
  146     int te_ALIVEPORTS;
  147     int te_Portid;
  148     int    *te_alives;
  149     int te_alivex;
  150     int    *te_actives;  /* ports waiting I/O */
  151     int te_activex;  /* the number of currently active ports */
  152     int te_waitingQ; /* the top port in waiting queue */
  153 
  154     int te_numAccept;
  155     int te_numConnect;
  156     int te_numSEND;
  157     int te_numRECV;
  158     int te_numSUSP;
  159     int te_numPackSEND;
  160     int te_numPackRECV;
  161     int te_maxAlive;
  162     int te_numPrefetchHIT;
  163     int te_numPrefetchMISS;
  164     int te_Ni;
  165     int te_Nn;
  166 
  167   const char   *te_router;
  168   const char   *te_server;
  169     MStr(   te_server_host,128);
  170     int te_server_port;
  171     MStr(   te_router_host,128);
  172     int te_router_port;
  173     int te_dbg_http;
  174     int te_clockN;
  175     MStr(   te_svhost0,128);
  176     int te_svport0;
  177     MStr(   te_Sctlbuf,64);
  178 } ThruWayEnv;
  179 static ThruWayEnv *thruWayEnv;
  180 #define TWE     thruWayEnv[0]
  181 
  182 #define LOGFP       TWE.te_LOGFP
  183 #define logisatty   TWE.te_logisatty
  184 #define prefetched  TWE.te_prefetched
  185 #define PACKID      TWE.te_PACKID
  186 #define dbglev      TWE.te_dbglev
  187 #define CONN_PREFECH    TWE.te_CONN_PREFECH
  188 
  189 #define NUMPORTS    TWE.te_NUMPORTS
  190 #define ports       TWE.te_ports
  191 #define ALIVEPORTS  TWE.te_ALIVEPORTS
  192 #define Portid      TWE.te_Portid
  193 #define alives      TWE.te_alives
  194 #define alivex      TWE.te_alivex
  195 #define actives     TWE.te_actives
  196 #define activex     TWE.te_activex
  197 #define waitingQ    TWE.te_waitingQ
  198 
  199 #define numAccept   TWE.te_numAccept
  200 #define numConnect  TWE.te_numConnect
  201 #define numSEND     TWE.te_numSEND
  202 #define numRECV     TWE.te_numRECV
  203 #define numSUSP     TWE.te_numSUSP
  204 #define numPackSEND TWE.te_numPackSEND
  205 #define numPackRECV TWE.te_numPackRECV
  206 #define maxAlive    TWE.te_maxAlive
  207 #define numPrefetchHIT  TWE.te_numPrefetchHIT
  208 #define numPrefetchMISS TWE.te_numPrefetchMISS
  209 #define Ni      TWE.te_Ni
  210 #define Nn      TWE.te_Nn
  211 
  212 #define router      TWE.te_router
  213 #define server      TWE.te_server
  214 #define server_host TWE.te_server_host
  215 /**/
  216 #define server_port TWE.te_server_port
  217 #define router_host TWE.te_router_host
  218 /**/
  219 #define router_port TWE.te_router_port
  220 #define dbg_http    TWE.te_dbg_http
  221 #define clockN      TWE.te_clockN
  222 #define Svhost0     TWE.te_svhost0
  223 /**/
  224 #define svport0     TWE.te_svport0
  225 #define Sctlbuf     TWE.te_Sctlbuf
  226 /**/
  227 
  228 #define LOG (LOGFP?LOGFP:stderr)
  229 #define LD dbglev<2?0:dbglog
  230 #define LE dbglev<1?0:dbglog
  231 
  232 
  233 int isSocksConnect(PCStr(pack),int leng,int *ver,PVStr(addr),int *port,const char **user);
  234 int RIDENT_send(int sock,PCStr(sockname),PCStr(peername),PCStr(ident));
  235 
  236 static void dumpQactive(FILE *fp);
  237 static void dumpQwaiting(FILE *fp);
  238 static void ackBSOCKS(IOPORT *pp,PCStr(ver));
  239 static void enQactive(int sock);
  240 static void deQactive(int sock);
  241 static int deQwaiting(int delsock);
  242 static int rewriteHTTPreq(IOPORT *PP,int IO);
  243 static void bsocks_init();
  244 static int relay(int src,int dst,int rwccoff);
  245 static void bsock_server(int svsockn,int svsocks[]);
  246 static void set_BUSBUF(int bsock);
  247 static int connError(PCStr(where),int sock,PCStr(host),int port,int _errno);
  248 static int try_identify(IOPORT *PP,int IO);
  249 static int notify_connected(IOPORT *PP,int dsock);
  250 static void putMSG(int dsock,PCStr(buff),int len);
  251 static void shift_buff(IOPORT *dp);
  252 static int getPackHead(int src,PCStr(msg),int rleng,int *rport,int *portid,int *packid,int *pleng,int *control,int *ctlarg);
  253 static int putPackHead(char msg[],IOPORT *pp,int leng,int control,int ctlarg);
  254 static int waitFlushed(IOPORT *pp,int wcc);
  255 static void pollFlushed(IOPORT *pp);
  256 static void notifyEOF(IOPORT *pp);
  257 static void clock1(int sockx,int IO);
  258 static void connectFromBSOCKS(int bsock,int rport,int rbuff,PCStr(cmd),int clen);
  259 static void connectAtRemote(int bsock,int ssock);
  260 static void notify_connectingR(int sock,int _errno);
  261 static void notify_connectedR(int sock,int _errno);
  262 static int try_identify(IOPORT *PP,int IO);
  263 static void notifyFlushed(IOPORT *pp,int wcc);
  264 
  265 void minit_thruway()
  266 {
  267     if( thruWayEnv == 0 ){
  268         thruWayEnv = NewStruct(ThruWayEnv);
  269         dbglev = 1;
  270         CONN_PREFECH = 1;
  271     }
  272 }
  273 
  274 static int dbglog(FILE *log,PCStr(fmt),...)
  275 {   CStr(stime,64);
  276     const char *sp;
  277     VARGS(14,fmt);
  278 
  279     getTimestamp(AVStr(stime));
  280     sp = strchr(stime,'-') + 1;
  281     fprintf(log,"%d %s ",clockN,sp);
  282     fprintf(log,fmt,VA14);
  283 /*
  284     if( !logisatty )
  285         fflush(log);
  286 */
  287     return 0;
  288 }
  289 
  290 static void dumpstat(int out);
  291 static void sigINT(int sig){
  292     LE(LOG,"GOT SIGINT/SIGTERM\n");
  293     dumpstat(fileno(LOG));
  294     exit(0);
  295 }
  296 
  297 extern int DNS_TIMEOUT;
  298 extern int RSLV_TIMEOUT;
  299 extern int RSLV_TIMEDOUT;
  300 
  301 /*
  302  * THRUWAY_ENTR is like MASTER in DeleGate which points to destination server
  303  * THRUWAY_EXIT is like SERVER in DeleGate which points to mediator DeleGate
  304  */
  305 int thruwayd_main(int ac,const char *av[])
  306 {   ACStr(svhosts,64,64);
  307     int svports[64],svsocks[64];
  308     CStr(host,64);
  309     const char *arg;
  310     const char *env;
  311     int svportn,svsockn;
  312     int ai,port,sock;
  313 
  314     minit_thruway();
  315 
  316     DNS_TIMEOUT = 1;
  317     if( isatty(fileno(LOG)) ){
  318         fprintf(LOG,"Thruwayd [-P[host:]port]    \n");
  319         fprintf(LOG,"   [THRUWAY_ENTR=host:port] \n");
  320         fprintf(LOG,"   [THRUWAY_EXIT=host:port] \n");
  321         fprintf(LOG,"   [LOGFILE=path]           \n");
  322         logisatty = 1;
  323     }
  324 
  325     svportn = 0;
  326     svsockn = 0;
  327 
  328     if( env = getenv("THRUWAY_ENTR") )
  329         router = env;
  330     if( env = getenv("THRUWAY_EXIT") )
  331         server  = env;
  332 
  333     if( fromInetd() ){
  334         sock = 1;
  335         port = sockPort(sock);
  336         svsocks[svsockn++] = sock;
  337     }
  338 
  339     for( ai = 1; ai < ac; ai++ ){
  340         arg = av[ai];
  341         if( arg[0] == '-' ){
  342             if( strcmp(&arg[1],"ringer") == 0 ){
  343                 if( router == NULL ) router = TW_ENTR0;
  344                 if( server == NULL ) server = TW_EXIT0;
  345             }else
  346             switch( arg[1] ){
  347                 case 'v':
  348                 if( arg[2] == 'v' )
  349                     dbglev = 2;
  350                 else{
  351                     dbglev = atoi(&arg[2]);
  352                     if( dbglev == 0 )
  353                         dbglev = 1;
  354                 }
  355                 break;
  356                 case 'P':
  357                 host[0] = 0;
  358                 port = atoi(arg+2);
  359                 if( port == 0 )
  360                     Xsscanf(arg+2,"%[^:]:%d",AVStr(host),&port);
  361                 if( 0 < port ){
  362                     Xstrcpy(EVStr(svhosts[svportn]),host);
  363                     svports[svportn++] = port;
  364                 }
  365                 break;
  366                 default:
  367                 LE(LOG,"unknown option: [%d] %s\n",ai,arg);
  368                 break;
  369             }
  370         }else
  371         if( strncmp(arg,"LOGFILE=",8) == 0 ){
  372             FILE *fp;
  373             fp = fopen(arg+8,"a");
  374             if( fp == NULL ){
  375                 fprintf(LOG,"ThruWay: cannot open: %s\n",
  376                     arg+8);
  377                 exit(1);
  378             }
  379             LOGFP = fp;
  380         }else
  381         if( strncmp(arg,"THRUPATH=",9) == 0 ){
  382         }else
  383         if( strncmp(arg,"THRUWAY_ENTR=",13) == 0 ){
  384             router = arg+13;
  385         }else
  386         if( strncmp(arg,"THRUWAY_EXIT=",13) == 0 ){
  387             server = arg+13;
  388         }else
  389         if( strncmp(arg,"RIDENT=",7) == 0 ){
  390             /*
  391             scan_RIDENT(arg+7);
  392             */
  393             scan_RIDENT(NULL,arg+7);
  394             LE(LOG,"RIDENT=%s\n",arg+7);
  395         }else
  396         {
  397             LE(LOG,"unknown argument: [%d] %s\n",ai,arg);
  398         }
  399     }
  400 
  401     if( svsockn == 0 && svportn == 0 )
  402         svports[svportn++] = TW_PORT;
  403 
  404     for( ai = 0; ai < svportn; ai++ ){
  405         port = svports[ai];
  406         sock = server_open("bsockd",EVStr(svhosts[ai]),port,1);
  407         if( 0 <= sock ){
  408             svsocks[svsockn++] = sock;
  409 LE(LOG,"THRUWAY_PORT = %s %d/%d\n",svhosts[ai],port,sock);
  410 
  411 if( svhosts[ai][0] == 0 )
  412     gethostname(Svhost0,sizeof(Svhost0));
  413 else    strcpy(Svhost0,svhosts[ai]);
  414 svport0 = port;
  415         }
  416     }
  417 
  418     if( router ){
  419 LE(LOG,"THRUWAY_ENTR = %s\n",router);
  420         Xsscanf(router,"%[^:]:%d",AVStr(router_host),&router_port);
  421         if( router_port == 0 ){
  422             LE(LOG,"Usage: THRUWAY_ENTR=host:port");
  423             exit(1);
  424         }
  425     }
  426     if( server ){
  427 LE(LOG,"THRUWAY_EXIT = %s\n",server);
  428         Xsscanf(server,"%[^:]:%d",AVStr(server_host),&server_port);
  429         if( server_port == 0 ){
  430             LE(LOG,"Usage: THRUWAY_EXIT=host:port");
  431             exit(1);
  432         }
  433     }
  434 
  435 #ifdef SIGPIPE
  436     signal(SIGPIPE,SIG_IGN);
  437 #endif
  438 #ifdef SIGTERM
  439     signal(SIGTERM,sigINT);
  440 #endif
  441     signal(SIGINT,sigINT);
  442     bsocks_init();
  443     bsock_server(svsockn,svsocks);
  444     LE(LOG,"done.\n");
  445     dumpstat(2);
  446     return 0;
  447 }
  448 
  449 void service_bsocks(DGC*Conn)
  450 {
  451     minit_thruway();
  452 }
  453 
  454 #define P_ERROR     -1
  455 #define P_MORE      -2
  456 #define P_UNDEF     0
  457 #define P_BSOCKS    1
  458 #define P_SOCKS4    2
  459 #define P_HTTP      3
  460 #define P_TBSOCKS   4
  461 
  462 #define CTL_HELLO   0x01    /* opening */
  463 #define CTL_CONNECTDO   0x02    /* make connect at remote router */
  464 #define CTL_CONNECTING  0x04    /* < connecting at remote router */
  465 #define CTL_CONNECTED   0x08    /* < connected at remote router */
  466 #define CTL_CONNERR 0x10    /* < connection error occured at remote router*/
  467 #define CTL_DATA    0x20    /* data */
  468 #define CTL_SENT    0x40    /* < sent N bytes (total) */
  469 #define CTL_EOF     0x80    /* < EOF occured */
  470 #define CTL_ACCEPTDO    0x0400  /* accept at remote router */
  471 #define CTL_ACCEPTED    0x0800  /* < accepted at remote router */
  472 
  473 static const char *sctl(int ctl)
  474 {   MrefQStr(cp,Sctlbuf); /**/
  475 
  476     McpyQStr(cp,Sctlbuf);
  477     setVStrEnd(cp,0);
  478     if( ctl & CTL_HELLO      ){ strcpy(cp,"Helo"), cp += strlen(cp); }
  479     if( ctl & CTL_CONNECTDO  ){ strcpy(cp,"Conn"), cp += strlen(cp); }
  480     if( ctl & CTL_CONNECTING ){ strcpy(cp,"Cing"); cp += strlen(cp); }
  481     if( ctl & CTL_CONNECTED  ){ strcpy(cp,"Coed"); cp += strlen(cp); }
  482     if( ctl & CTL_CONNERR    ){ strcpy(cp,"Cerr"); cp += strlen(cp); }
  483     if( ctl & CTL_ACCEPTDO   ){ strcpy(cp,"Acc");  cp += strlen(cp); }
  484     if( ctl & CTL_ACCEPTED   ){ strcpy(cp,"Aced"); cp += strlen(cp); }
  485     if( ctl & CTL_DATA       ){ strcpy(cp,"Data"); cp += strlen(cp); }
  486     if( ctl & CTL_SENT       ){ strcpy(cp,"Sent"); cp += strlen(cp); }
  487     if( ctl & CTL_EOF        ){ strcpy(cp,"Eof");  cp += strlen(cp); }
  488     return Sctlbuf;
  489 }
  490 
  491 /*
  492  *  reasons of closing
  493  */
  494 /* destroy immediately */
  495 #define CLOSE_INITERROR     0x01
  496 #define CLOSE_LOCALEOF      0x02
  497 #define CLOSE_CONNERROR     0x04
  498 
  499 /* destroy after output drain */
  500 #define CLOSE_LOCALPEER     0x08
  501 #define CLOSE_BUSEOF        0x10
  502 #define CLOSE_REMOTEPEER    0x20
  503 
  504 /*
  505  *  STATUS OF I/O PORTS
  506  */
  507 #define ST_INACTIVE 0   /* inactive */
  508 
  509 /* input port */
  510 #define ST_ACCEPT   0x001   /* accepting       ... poll(RECV)  */
  511 #define ST_ACCEPT_WAIT  0x2000  /* waiting local port to accept    */
  512 #define ST_INIT     0x002   /* initializing    ... poll(RECV)  */
  513 #define ST_RESOLV   0x004   /* resolving ... watch(eof,dns,timeout) */
  514 #define ST_RECV     0x008   /* receiving       ... poll(RECV)  */
  515 #define ST_WAIT_SEND    0x010   /* waiting local output to be drained */
  516 #define ST_WAIT_RFLUSH  0x020   /* waiting remote output to be drained */
  517 
  518 /* output port */
  519 #define ST_CONNECT  0x100   /* connecting      ... poll(SEND)  */
  520 #define ST_RCONNECT 0x200   /* waiting remote connection */
  521 #define ST_READY    0x400   /* waiting output */
  522 #define ST_SEND     0x800   /* sending         ... poll(SEND)  */
  523 #define ST_CONNPRE  0x1000  /* prefetched connection */
  524 
  525 #define ST_POLLRECV (ST_ACCEPT|ST_INIT|ST_RECV)
  526 #define ST_POLLSEND (ST_CONNECT|ST_SEND)
  527 #define ST_WAITING  (ST_WAIT_SEND|ST_WAIT_RFLUSH)
  528 
  529 static const char *ss(int stat)
  530 {   switch( stat ){
  531       case ST_ACCEPT:   return "ACC";
  532       case ST_ACCEPT_WAIT:  return "WAC";
  533       case ST_INIT:     return "INI";
  534       case ST_RESOLV:   return "DNS";
  535       case ST_RECV:     return "RCV";
  536       case ST_WAIT_SEND:    return "WSN";
  537       case ST_SEND:     return "SND";
  538       case ST_CONNPRE:  return "CPF";
  539       case ST_CONNECT:  return "CON";
  540       case ST_RCONNECT: return "RCO";
  541       case ST_READY:    return "RDY";
  542       case ST_WAIT_RFLUSH:  return "WRF";
  543     }
  544     return "INA";
  545 }
  546 
  547 static void bsocks_init()
  548 {
  549     NUMPORTS = expand_fdset(MAXPORTS);
  550     ports = (IOPORT**)calloc(sizeof(IOPORT*),NUMPORTS);
  551     alives = (int*)calloc(sizeof(int),NUMPORTS);
  552     actives = (int*)calloc(sizeof(int),NUMPORTS);
  553 }
  554 
  555 #define W_IN        0
  556 #define W_OUT       1
  557 
  558 #define P_PROTO     PP->p_proto
  559 #define P_SOCK      PP->p_lport
  560 
  561 #define P_STATUS    PP->io[IO].p_status
  562 #define P_RWCC      PP->io[IO].p_rwcc
  563 #define P_BUFSIZE   PP->io[IO].p_bsize
  564 #define P_BUFLEN    PP->io[IO].p_bleng
  565 #define P_BUFF      PP->io[IO].p_buff
  566 #define P_REMCC     ((IO==W_IN?P_BUFSIZE:P_BUFLEN) - P_RWCC)
  567 #define P_IOTOTAL   PP->io[IO].p_iototal
  568 #define P_IOCOUNT   PP->io[IO].p_iocount
  569 #define P_EOF       PP->p_EOF
  570 
  571 #define P_DHOST     PP->p_dsthost
  572 /**/
  573 #define P_DPORT     PP->p_dstport
  574 #define P_DSOCK     PP->p_dstsock
  575 #define P_SSOCK     PP->p_srcsock
  576 #define P_BHOST     PP->p_bhost
  577 /**/
  578 #define P_BPORT     PP->p_bport
  579 #define P_RPORT     PP->p_rport
  580 
  581 /* OUTSTANDING:
  582  * total read - left in read buffer + drained at remote output
  583  */
  584 #define outstanding(pp) \
  585     (pp->p_rport ? (pp->io[W_IN].p_iototal - \
  586         (pp->io[W_IN].p_rwcc + pp->io[W_IN].p_remotetotal)) : 0)
  587 
  588 static void dumpstat(int out)
  589 {   FILE *fp;
  590     int pi;
  591     IOPORT *pp;
  592     CStr(srcsock,128);
  593 
  594     fp = fdopen(dup(out),"w");
  595     fprintf(fp,"  MaxAlive=%d",maxAlive);
  596     fprintf(fp,"  Accepted=%d",numAccept);
  597     fprintf(fp,"  Connected=%d",numConnect);
  598     fprintf(fp,"  Prefetched=%dhit:%dmiss",numPrefetchHIT,numPrefetchMISS);
  599     fprintf(fp,"\n");
  600     fprintf(fp,"  Active=%d",activex); dumpQactive(fp);
  601     fprintf(fp,"\n");
  602     fprintf(fp,"  Waiting=",waitingQ); dumpQwaiting(fp);
  603     fprintf(fp,"\n");
  604     fprintf(fp,"  Raw-I/O: SEND=%d RECV=%d SUSP=%d\n",
  605         numSEND,numRECV,numSUSP);
  606     fprintf(fp,"  Pack-I/O: SEND=%d RECV=%d\n",
  607         numPackSEND,numPackRECV);
  608 
  609     for( pi = 0; pi < NUMPORTS; pi++ )
  610     if( pp = ports[pi] ){
  611         if( pp->p_proto == P_BSOCKS )
  612             strcpy(srcsock,"*");
  613         else    sprintf(srcsock,"%x",pp->p_srcsock);
  614 
  615         fprintf(fp,"%4x[%2x]%s %4x",
  616             pp->p_portid,pi,srcsock,
  617             pp->p_rport
  618         );
  619         fprintf(fp," I[%s %d %d(%d)/%d]",
  620             ss(pp->io[W_IN].p_status),
  621             pp->io[W_IN].p_rwcc,
  622             pp->io[W_IN].p_iototal,
  623             outstanding(pp),
  624             pp->io[W_IN].p_iocount
  625         );
  626         fprintf(fp," O[%s %d/%d %d(%d)/%d]",
  627             ss(pp->io[W_OUT].p_status),
  628             pp->io[W_OUT].p_rwcc,
  629             pp->io[W_OUT].p_bleng,
  630             pp->io[W_OUT].p_iototal,
  631             pp->io[W_OUT].p_notifiedcc,
  632             pp->io[W_OUT].p_iocount
  633         );
  634         if( pp->p_EOF ) fprintf(fp,"[EOF]");
  635         if( pp->p_closing ) fprintf(fp,"[closing:%x]",pp->p_closing);
  636         if( pp->io[W_IN].p_pendingcc ){
  637             fprintf(fp,">[%d]%d",
  638                 pp->io[W_IN].p_pendingto,
  639                 pp->io[W_IN].p_pendingcc);
  640         }
  641         if( pp->io[W_OUT].p_status == ST_CONNECT )
  642             fprintf(fp," (%s:%d)",pp->p_dsthost,pp->p_dstport);
  643         else{
  644             CStr(hostport,128);
  645             getpeerName(pi,AVStr(hostport),"%H:%P");
  646             fprintf(fp," %s",hostport);
  647         }
  648         if( pp->p_proto == P_BSOCKS && pp->p_bhost[0] ){
  649             fprintf(fp," <%s:%d>",pp->p_bhost,pp->p_bport);
  650         }
  651         fprintf(fp,"\n");
  652     }
  653     fclose(fp);
  654 }
  655 
  656 /*
  657  *  Output buffer to external agent must be larger than possible
  658  *  buffered input in socket and peer router...
  659  *  SERVER[Bsv]R1[B1] =>[Bsock]=> [B2]R2[Bcl]CLIENT
  660  */
  661 #define BUFUNIT     (16*1024)
  662 #define IBUFSIZE    (2*BUFUNIT-HEADSIZE)
  663 #define OBUFSIZE    (4*BUFUNIT)
  664 #define BSOCKBUFSIZE    (8*BUFUNIT)
  665 #define BHEAD_MARGIN    1024
  666 
  667 #define enPortID(ptp)   ((ptp->p_lport<<8)|(ptp->p_portid&0xFF))
  668 static int dePortID(int pti)
  669 {   IOPORT *pp;
  670     int lport,portid;
  671 
  672     portid = pti & 0xFF;
  673     lport = pti >> 8;
  674     pp = ports[lport];
  675     if( pp == NULL ){
  676         LD(LOG,"[%x] ## DANGLING PORT SOCK (%x)\n",lport,pti);
  677         return -1;
  678     }
  679     if( (pp->p_portid & 0xFF) != portid ){
  680         LD(LOG,"[%x] ## OVERWRITEN PORT (%x)\n",lport,portid);
  681         return -1;
  682     }
  683     return lport;
  684 }
  685 
  686 static void new_port(PCStr(where),int src,int sock)
  687 {   IOPORT *np;
  688 
  689     LD(LOG,"[%x] new_port(%s,%d)\n",src,where,sock);
  690     if( sock < 0 )
  691         exit(-1);
  692 
  693     /* ... should try to get from free list of IOPORT structure ... */
  694     np = (IOPORT*)calloc(1,sizeof(IOPORT));
  695 
  696     np->p_portid = ++Portid;
  697     np->p_lport = sock;
  698     np->p_ctime = time(NULL);
  699     setQStr(np->io[W_IN].p_buff,(char*)malloc(BHEAD_MARGIN+IBUFSIZE),BHEAD_MARGIN+IBUFSIZE);
  700     np->io[W_IN].p_bsize = BUFUNIT;
  701     setQStr(np->io[W_OUT].p_buff,(char*)malloc(BHEAD_MARGIN+OBUFSIZE),BHEAD_MARGIN+OBUFSIZE);
  702     np->io[W_OUT].p_bsize = BUFUNIT;
  703     ports[sock] = np;
  704     ALIVEPORTS++;
  705     if( maxAlive < ALIVEPORTS )
  706         maxAlive = ALIVEPORTS;
  707 }
  708 static void del_port(int sock)
  709 {   int pi;
  710     IOPORT *dp,*pp;
  711     int deq;
  712 
  713     if( ports[sock] == NULL ){
  714         LE(LOG,"[%x] del_port... NULL\n",sock);
  715         return;
  716     }
  717 
  718     dp = ports[sock];
  719     if( dp->p_proto == P_BSOCKS && !dp->p_EOF ){
  720         /*LE(LOG,"[%x] postpone del_port BSOCKS\n",sock);*/
  721         dp->p_closing = 0;
  722         return;
  723     }
  724 
  725     deq = deQwaiting(sock);
  726     LE(LOG,"[%x] <%x>(%d) %ds %d/%di %d/%do\n",sock,
  727         dp->p_portid,ALIVEPORTS-3,time(0)-dp->p_ctime,
  728         dp->io[W_IN].p_iototal, dp->io[W_IN].p_iocount,
  729         dp->io[W_OUT].p_iototal,dp->io[W_OUT].p_iocount
  730         );
  731 
  732     close(sock);
  733     dp->p_lport = -1;
  734 
  735     for( pi = 0; pi < NUMPORTS; pi++ )
  736     if( pp = ports[pi] )
  737     if( pp->p_dstsock == sock || pp->p_srcsock == sock )
  738         pp->p_closing |= CLOSE_LOCALPEER;
  739     else
  740     if( dp->io[W_OUT].p_status == ST_ACCEPT_WAIT
  741      && (pp->p_accsock == sock || pp->p_acclast == sock
  742      ||  pp->p_acceptQ == sock) ){
  743 LD(LOG,"#### [%x] MUST detach this vport from accept Q[%x].\n",
  744             sock,pi);
  745         if( pp->p_accsock == sock && pp->p_acclast == sock )
  746             pp->p_closing |= CLOSE_LOCALEOF;
  747     }
  748 
  749     deQactive(sock);
  750 
  751     /* ... to free list ... */
  752     free((char*)dp->io[W_IN].p_buff);
  753     free((char*)dp->io[W_OUT].p_buff);
  754     if( dp->p_sockname ) free((char*)dp->p_sockname);
  755     if( dp->p_peername ) free((char*)dp->p_peername);
  756     free(dp);
  757     ports[sock] = NULL;
  758     ALIVEPORTS--;
  759 }
  760 static int findLocalPort(int rport)
  761 {   int portid;
  762     int pi;
  763     IOPORT *pp;
  764 
  765     for( pi = 0; pi < NUMPORTS; pi++ )
  766     if( pp = ports[pi] )
  767     if( pp->p_rport == rport ){
  768         LE(LOG,"[%d] is local port of %x\n",pi,rport);
  769         return enPortID(pp);
  770     }
  771     return 0;
  772 }
  773 /*
  774  * Find the vport of which protocol is BSOCKS and is connected to
  775  * the BSOCKS server at the host:port.
  776  */
  777 static int findBSOCKS(PCStr(host),int port)
  778 {   int pi;
  779     IOPORT *pp;
  780 
  781     for( pi = 0; pi < NUMPORTS; pi++ )
  782     if( pp = ports[pi] )
  783     if( pp->p_proto == P_BSOCKS )
  784 {
  785 LD(LOG,"[%x] findBSOCKS: %s:%d %s:%d\n",pi,host,port,pp->p_bhost,pp->p_bport);
  786     if( pp->p_bport == port )
  787     if( strcmp(host,pp->p_bhost) == 0 )
  788         return pi;
  789 }
  790     return -1;
  791 }
  792 /*
  793  * Find the vport which is accepting at the host:port,
  794  * or create it if no such port exists.
  795  */
  796 static int findASOCK(PCStr(spec),int ssock)
  797 {   CStr(host,MaxHostNameLen);
  798     int port;
  799     int asock,listen;
  800     int pi;
  801     IOPORT *pp;
  802     int port1;
  803 
  804     host[0] = 0;
  805     port = 0;
  806     listen = 7;
  807     Xsscanf(spec,"%[^:]:%d:%d",AVStr(host),&port,&listen);
  808     if( strcmp(host,"*") == 0 )
  809         host[0] = 0;
  810 
  811     for( pi = 0; pi < NUMPORTS; pi++ )
  812     if( pp = ports[pi] ){
  813         if( pp->io[W_IN].p_status == ST_ACCEPT )
  814         if( pp->p_acclast ){
  815             port1 = sockPort(pp->p_lport);
  816             if( port1 == port ){
  817 
  818 LD(LOG,"PARALLEL ACCEPT at [%d] %d,%d\n",
  819 port,pp->p_acclast,ssock);
  820 ports[pp->p_acclast]->p_acceptQ = ssock;
  821 pp->p_acclast = ssock;
  822                 return pi;
  823             }
  824         }
  825     }
  826 
  827     asock = Socket1("bsocks",-1,"inet","tcp","bsocks", AVStr(host),port,
  828         NULL,0, listen,NULL,1);
  829     if( asock < 0 )
  830         return -1;
  831 
  832 LD(LOG,"[%x] NEW ACCEPT vport for [%x]\n",asock,ssock);
  833 
  834     new_port("ACCEPT",ssock,asock);
  835     ports[asock]->io[W_IN].p_status = ST_ACCEPT;
  836     ports[asock]->p_accsock = ssock;
  837 
  838 ports[asock]->p_acclast = ssock;
  839 
  840     enQactive(asock);
  841     return asock;
  842 }
  843 
  844 static int prefetch(PCStr(where),int ssock,PCStr(host),int port)
  845 {   int sock;
  846     IOPORT *pp;
  847 
  848     if( host == 0 || *host == 0 || port == 0 )
  849         return -1;
  850 
  851     sock = Socket1("bsocks",-1,"inet","tcp","bsocks", VStrNULL,0,
  852         host,port, 0,NULL,1);
  853     if( sock < 0 )
  854         return -1;
  855     if( connError(where,sock,host,port,errno) ){
  856         close(sock);
  857         return -1;
  858     }
  859     new_port(where,ssock,sock);
  860     pp = ports[sock];
  861     strcpy(pp->p_dsthost,host);
  862     pp->p_dstport = port;
  863     pp->io[W_OUT].p_status = ST_CONNPRE;
  864     return sock;
  865 }
  866 
  867 static int newsocket(PCStr(where),int ssock,PCStr(host),int port)
  868 {   int sock;
  869     IOPORT *pp;
  870 
  871     if( router == NULL )
  872     for( sock = 0; sock < NUMPORTS; sock++ )
  873     if( pp = ports[sock] )
  874     if( pp->io[W_OUT].p_status == ST_CONNPRE )
  875     if( strcmp(host,pp->p_dsthost) == 0 )
  876     if( port == pp->p_dstport ){
  877         prefetched--;
  878         /* PollOut() ? */
  879         if( PollIn(sock,1) && Peek1(sock) <= 0 ){
  880             numPrefetchMISS++;
  881             LD(LOG,"[%x] TIMEOUT prefetched connection %s:%d\n",
  882                 sock,host,port);
  883             del_port(sock);
  884         }else{
  885             numPrefetchHIT++;
  886             LD(LOG,"[%x] VALID prefetched connection %s:%d\n",
  887                 sock,host,port);
  888             pp->p_ctime = time(NULL);
  889             return sock;
  890         }
  891     }
  892     return prefetch(where,ssock,host,port);
  893 }
  894 
  895 static void init_bhostport(PVStr(bhost),int *bportp)
  896 {
  897     setVStrEnd(bhost,0);
  898     *bportp = 0;
  899     if( router ){
  900         strcpy(bhost,router_host);
  901         *bportp = router_port;
  902     }
  903 }
  904 
  905 static int identify_protocol(IOPORT *PP,int IO)
  906 {   const char *elp;
  907     CStr(host,512);
  908     int port;
  909     const char *user;
  910     int leng;
  911     CStr(op,128);
  912     CStr(ver,128);
  913     int sver;
  914     CStr(bhost,512);
  915     int bport,rport;
  916     int proto = P_UNDEF;
  917     int rcode;
  918     CStr(msg,128);
  919     CStr(callback,128);
  920 
  921     callback[0] = 0;
  922     setVStrEnd(P_BUFF,P_RWCC);
  923 
  924     init_bhostport(AVStr(bhost),&bport);
  925     if( bhost[0] && bport ){
  926         strcpy(P_BHOST,bhost);
  927         P_BPORT = bport;
  928     }
  929 
  930     if( strncasecmp(P_BUFF,"STAT",4) == 0 ){
  931         dumpstat(P_SOCK);
  932         proto = P_ERROR;
  933     }else
  934     if( 8 <= P_RWCC && strncasecmp(P_BUFF,"ACCEPT ",7) == 0 ){
  935         CStr(sockhost,MaxHostNameLen);
  936         int asock;
  937 
  938         /* if not local port */
  939         if( bhost[0] && bport )
  940         if( elp = strchr(P_BUFF,'\n') ){
  941             elp++;
  942             leng = elp - P_BUFF;
  943             Bcopy(elp,P_BUFF,P_RWCC-leng);
  944             P_RWCC -= leng;
  945 
  946             if( Xsscanf(P_BUFF+7,"%[^:]:%d/%[^:]:%d/%d",AVStr(host),&port,AVStr(bhost),&bport,&rport) < 2 ){
  947                 del_port(PP->p_lport);
  948                 return -1;
  949             }
  950             P_PROTO = P_TBSOCKS;
  951             strcpy(P_DHOST,host);
  952             P_DPORT = 100000 + port;
  953             strcpy(P_BHOST,bhost);
  954             P_BPORT = bport;
  955 LD(LOG,"[%x] P_TBSOCKS: Raccept %s:%d\n",PP->p_lport,host,port);
  956             return P_TBSOCKS;
  957         }
  958 
  959         P_RWCC = 0;
  960         asock = findASOCK(P_BUFF+7,PP->p_lport);
  961         if( asock < 0 )
  962             return -1;
  963         PP->io[W_OUT].p_status = ST_ACCEPT_WAIT;
  964 /*
  965         gethostName(asock,sockhost,"%A:%P");
  966         PP->p_accsock = asock;
  967         sprintf(PP->io[W_OUT].p_buff,"BOUND %s\r\n",sockhost);
  968         PP->io[W_OUT].p_bleng = strlen(PP->io[W_OUT].p_buff);
  969         PP->io[W_OUT].p_status = ST_SEND;
  970 */
  971     }else
  972     if( 8 <= P_RWCC && strncasecmp(P_BUFF,"CONNECT ",8) == 0 ){
  973         if( elp = strchr(P_BUFF,'\n') ){
  974             elp++;
  975             leng = elp - P_BUFF;
  976             Bcopy(elp,P_BUFF,P_RWCC-leng);
  977             P_RWCC -= leng;
  978 
  979             if( Xsscanf(P_BUFF+8,"%[^:]:%d/%[^:]:%d/%d",AVStr(host),&port,AVStr(bhost),&bport,&rport) < 2 ){
  980                 del_port(PP->p_lport);
  981                 return -1;
  982             }
  983             P_PROTO = P_TBSOCKS;
  984             strcpy(P_DHOST,host);
  985             P_DPORT = port;
  986             if( bhost[0] && bport ){
  987                 strcpy(P_BHOST,bhost);
  988                 P_BPORT = bport;
  989             }
  990             proto = P_TBSOCKS;
  991 LD(LOG,"[%x] P_TBSOCKS: connect %s:%d\n",PP->p_lport,host,port);
  992         }
  993     }else
  994     if( 8 <= P_RWCC && (leng = isSocksConnect(P_BUFF,P_RWCC,&sver,AVStr(host),&port,&user)) ){
  995         proto = P_SOCKS4;
  996         P_PROTO = P_SOCKS4;
  997         strcpy(P_DHOST,host);
  998         P_DPORT = port;
  999 LD(LOG,"[%x] P_SOCKS%d: CONNECT %s:%d %s (%d/%d)\n",PP->p_lport,
 1000 sver,host,port,user,leng,P_RWCC);
 1001         Bcopy(P_BUFF+leng,P_BUFF,P_RWCC-leng);
 1002         P_RWCC -= leng;
 1003     }else
 1004     if( 8 <= P_RWCC && strncmp(P_BUFF,"BSOCKS/",7) == 0
 1005      && Xsscanf(P_BUFF,"BSOCKS/%s %s",AVStr(ver),AVStr(callback)) >= 1 ){
 1006         proto = P_BSOCKS;
 1007         P_PROTO = P_BSOCKS;
 1008         strcpy(P_DHOST,"");
 1009         P_DPORT = 0;
 1010         ackBSOCKS(PP,ver);
 1011 
 1012 LD(LOG,"####[%x] BSOCK CLEAR [%s:%d] AND SET [%s]\n",
 1013 PP->p_lport,P_BHOST,P_BPORT,callback);
 1014 Xsscanf(callback,"%[^:]:%d",AVStr(P_BHOST),&P_BPORT);
 1015 
 1016         if( elp = strchr(P_BUFF,'\n') ){
 1017             elp++;
 1018             leng = elp - P_BUFF;
 1019             Bcopy(elp,P_BUFF,P_RWCC-leng);
 1020             P_RWCC -= leng;
 1021 if( 0 < P_RWCC )
 1022 relay(P_SOCK,P_DSOCK,0); /* CONNECT... */
 1023 
 1024         }else   P_RWCC = 0;
 1025         set_BUSBUF(PP->p_lport);
 1026     }else
 1027     if( server ){
 1028         P_PROTO = P_TBSOCKS;
 1029         strcpy(P_DHOST,server_host);
 1030         P_DPORT = server_port;
 1031         proto = P_PROTO;
 1032     }else
 1033     if( 8 <= P_RWCC && (proto = rewriteHTTPreq(PP,IO /*,host,&port*/ )) ){
 1034     }else
 1035     if( strncmp(P_BUFF,"DeleGate-HELLO",15) == 0 ){
 1036     }else
 1037     if(  8 < P_RWCC ){
 1038         LE(LOG,"[%x] ERROR: protocol not identified\n",P_SOCK);
 1039         proto = P_ERROR;
 1040     }
 1041 
 1042     if( proto == P_MORE )
 1043         proto = P_UNDEF;
 1044     return proto;
 1045 }
 1046 static int rewriteHTTPreq(IOPORT *PP,int IO)
 1047 {   refQStr(up,P_BUFF); /**/
 1048     const char *vp;
 1049     const char *hp;
 1050     const char *rp;
 1051     CStr(hostport,512);
 1052     char sc;
 1053     const char *sp;
 1054     refQStr(dp,P_BUFF); /**/
 1055     CStr(host,512);
 1056     int prefix;
 1057     int port;
 1058     const char *cka;
 1059     int leng,remcc,rmcc,rmln;
 1060 
 1061     if( !HTTP_isMethod(P_BUFF) )
 1062         return 0;
 1063 
 1064     if( (up = strchr(P_BUFF,' ')) == NULL ){
 1065         LE(LOG,"[%x] BAD HTTP REQUEST\n",PP->p_lport);
 1066         return P_ERROR;
 1067     }
 1068     up++;
 1069     if( strncasecmp(up,"/-_-http://",11) == 0 ){
 1070         prefix = 11;
 1071     }else
 1072     if( strncasecmp(up,"http://",7) == 0 ){
 1073         prefix = 7;
 1074     }else{
 1075         LE(LOG,"[%x] BAD HTTP REQUEST\n",PP->p_lport);
 1076         return P_ERROR;
 1077     }
 1078     if( vp = strpbrk(up," \t\r\n") )
 1079         vp++;
 1080     if( vp && strncmp(vp,"HTTP/",5) == 0 )
 1081     if( strstr(P_BUFF,"\r\n\r\n") == NULL ){
 1082         LD(LOG,"[%x] INCOMPLETE HTTP REQUEST\n",PP->p_lport);
 1083         return P_MORE;
 1084     }
 1085 
 1086     hp = up + prefix;
 1087     rp = strpbrk(hp,"/ \t\r\n");
 1088     Bcopy(hp,hostport,rp-hp);
 1089     hostport[rp-hp] = 0;
 1090     port = 80;
 1091     Xsscanf(hostport,"%[^:]:%d",AVStr(host),&port);
 1092     leng = rp - up;
 1093     remcc = P_RWCC - (rp - P_BUFF);
 1094     if( *rp != '/' )
 1095         setVStrPtrInc(up,'/');
 1096     Bcopy(rp,up,remcc);
 1097 
 1098     dp = up;
 1099     rmln = 0;
 1100     rmcc = 0;
 1101     for( sp = up; sc = *sp++; ){
 1102         if( rmln )
 1103             rmcc++;
 1104         else    setVStrPtrInc(dp,sc);
 1105         if( sc != '\n' )
 1106             continue;
 1107 
 1108         if( rmln ){
 1109             rmln = 0;
 1110         }else
 1111         if( strncasecmp(sp,"Proxy-Connection:",17) == 0
 1112          || strncasecmp(sp,"Connection:",11) == 0 ){
 1113             LD(LOG,"removed Connection: field\n");
 1114             rmln = 1;
 1115         }
 1116     }
 1117 
 1118     P_RWCC = (up - P_BUFF) + remcc - rmcc;
 1119     P_PROTO = P_HTTP;
 1120     strcpy(P_DHOST,host);
 1121     P_DPORT = port;
 1122     setVStrEnd(P_BUFF,P_RWCC);
 1123 
 1124 if( dbg_http )
 1125 fprintf(LOG,"HTTP[%s:%d]LENG=%d+%d\n%s\n",P_DHOST,P_DPORT,P_RWCC,rmcc,P_BUFF);
 1126 
 1127     return P_HTTP;
 1128 }
 1129 
 1130 static int try_send(int src)
 1131 {   IOPORT *sp,*dp;
 1132     int dst;
 1133 
 1134     sp = ports[src];
 1135     dst = sp->io[W_IN].p_waitdst;
 1136     if( dst == 0 ){
 1137         LD(LOG,"[%x] SEND TO SOMETHING(%d)\n",src,sp->p_dstsock);
 1138         return relay(src,sp->p_dstsock,0);
 1139     }
 1140 
 1141     dp = ports[dst];
 1142     if( dp == 0 ){
 1143         int rwcc,rmcc;
 1144         refQStr(buff,sp->io[W_IN].p_buff); /**/
 1145         rwcc = sp->io[W_IN].p_rwcc;
 1146         rmcc = sp->io[W_IN].p_waitingcc;
 1147         buff = (char*)sp->io[W_IN].p_buff;
 1148         sp->io[W_IN].p_waitdst = 0;
 1149 
 1150 fprintf(LOG,"[%x]%s > %x #### SEND TO ZOMBI #### remove(%d/%d)\n",
 1151 src,sp->p_proto==P_BSOCKS?"*":" ",dst,rmcc,rwcc);
 1152 if( rmcc != rwcc ) sleep(5);
 1153 
 1154         if( sp->p_proto == P_BSOCKS ){
 1155             relay(src,0,0);
 1156         }else
 1157         if( rmcc && sp->p_proto == P_BSOCKS ){
 1158             Bcopy(buff+rmcc,buff,rwcc-rmcc);
 1159             sp->io[W_IN].p_waitingcc = 0;
 1160             sp->io[W_IN].p_rwcc -= rmcc;
 1161             relay(src,0,0);
 1162         }else{
 1163             sp->io[W_IN].p_rwcc = 0;
 1164             sp->io[W_IN].p_status = ST_RECV;
 1165         }
 1166         return 1;
 1167     }
 1168 
 1169     if( dp->io[W_OUT].p_status == ST_READY || sp->p_proto == P_BSOCKS )
 1170         return relay(src,dst,0);
 1171     return 0;
 1172 }
 1173 
 1174 static void enQactive(int sock)
 1175 {   int ai;
 1176 
 1177     for( ai = 0; ai < activex; ai++ )
 1178         if( actives[ai] == sock )
 1179             return;
 1180     actives[activex++] = sock;
 1181 }
 1182 static void deQactive(int sock)
 1183 {   int ai,ao,ndel;
 1184 
 1185     ao = 0;
 1186     ndel = 0;
 1187     for( ai = 0; ai < activex; ai++ ){
 1188         if( actives[ai] == sock )
 1189             ndel++;
 1190         else    actives[ao++] = actives[ai];
 1191     }
 1192     activex -= ndel;
 1193 }
 1194 
 1195 static void enQwaiting(int sockx)
 1196 {   IOPORT *pp;
 1197     int wq,nq;
 1198     int nwait;
 1199 
 1200     if( waitingQ == sockx )
 1201         return;
 1202 
 1203     if( waitingQ == 0 ){
 1204         waitingQ = sockx;
 1205         ports[sockx]->p_waitingQ = 0;
 1206         nwait = 1;
 1207     }else{
 1208         nwait = 1;
 1209         for( wq = waitingQ; 0 < (nq = ports[wq]->p_waitingQ); wq = nq ){
 1210             if( nq == sockx )
 1211                 return;
 1212             nwait++;
 1213         }
 1214         ports[wq]->p_waitingQ = sockx;
 1215         ports[sockx]->p_waitingQ = 0;
 1216         nwait++;
 1217     }
 1218     /*LD(LOG,"#### ENQ[%d] = %d\n",nwait,sockx);*/
 1219 }
 1220 static int inQwaiting(int sockq){
 1221     int sockx;
 1222     IOPORT *pp;
 1223 
 1224     for( sockx = waitingQ; 0 < sockx; sockx = pp->p_waitingQ ){
 1225         if( sockx == sockq )
 1226             return 1;
 1227         pp = ports[sockx];
 1228     }
 1229     return 0;
 1230 }
 1231 static void scanQwaiting(){
 1232     int sockx;
 1233     IOPORT *pp,*wq;
 1234     int ntrial;
 1235 
 1236     if( waitingQ == 0 )
 1237         return;
 1238 
 1239     ntrial = 0;
 1240     for( sockx = waitingQ; 0 < sockx; sockx = pp->p_waitingQ ){
 1241         pp = ports[sockx];
 1242         switch( pp->io[W_IN].p_status ){
 1243             case ST_WAIT_SEND:
 1244             try_send(sockx);
 1245             ntrial++;
 1246             break;
 1247             case ST_WAIT_RFLUSH:
 1248             pollFlushed(pp);
 1249             ntrial++;
 1250             break;
 1251         }
 1252     }
 1253 
 1254     wq = NULL;
 1255     if( ntrial )
 1256     for( sockx = waitingQ; 0 < sockx; sockx = pp->p_waitingQ ){
 1257         pp = ports[sockx];
 1258         if( (pp->io[W_IN].p_status & ST_WAITING) == 0 ){
 1259             if( wq == NULL )
 1260                 waitingQ = pp->p_waitingQ;
 1261             else    wq->p_waitingQ = pp->p_waitingQ;
 1262         }else   wq = pp;
 1263     }
 1264 }
 1265 static void dumpQactive(FILE *fp)
 1266 {   int pi;
 1267 
 1268     for( pi = 0; pi < activex; pi++ )
 1269         fprintf(fp,"(%x)",actives[pi]);
 1270 }
 1271 static void dumpQwaiting(FILE *fp)
 1272 {   int sockx;
 1273 
 1274     for( sockx = waitingQ; 0 < sockx; sockx = ports[sockx]->p_waitingQ )
 1275         fprintf(fp,"(%x)",sockx);
 1276 }
 1277 static int deQwaiting(int delsock)
 1278 {   int sockx;
 1279     IOPORT *wq,*pp;
 1280 
 1281     wq = NULL;
 1282     for( sockx = waitingQ; 0 < sockx; sockx = pp->p_waitingQ ){
 1283         pp = ports[sockx];
 1284         if( sockx == delsock ){
 1285             if( wq == NULL )
 1286                 waitingQ = pp->p_waitingQ;
 1287             else    wq->p_waitingQ = pp->p_waitingQ;
 1288             return 1;
 1289         }
 1290         wq = pp;
 1291     }
 1292     return 0;
 1293 }
 1294 
 1295 static void bsock_server(int svsockn,int svsocks[])
 1296 {   int svsock1;
 1297     int fi,qfdv[MAXPORTS],rfdv[MAXPORTS];
 1298     int pq,cactives[MAXPORTS],cactivex;
 1299     int nready,timeout;
 1300     int px,sockx;
 1301     int wx;
 1302     IOPORT *pp,*bp;
 1303     int status;
 1304     int nac,nai;
 1305 
 1306     timeout = 1*1000;
 1307     new_port("INIT",-1,0); /* to internal */
 1308     for( fi = 0; fi < svsockn; fi++ ){
 1309         svsock1 = svsocks[fi];
 1310         new_port("INIT",-1,svsock1); /* given entrance */
 1311         ports[svsock1]->io[W_IN].p_status = ST_ACCEPT;
 1312         enQactive(svsock1);
 1313     }
 1314 
 1315     if( router == NULL && server != NULL )
 1316     if( 0 <= prefetch("prefetch",-1,server_host,server_port) )
 1317         prefetched++;
 1318 
 1319     for( clockN = 1;; clockN++ ){
 1320         cactivex = 0;
 1321         for( fi = 0; fi < activex; fi++ ){
 1322             IOPORT *pp;
 1323 
 1324             sockx = actives[fi];
 1325             pp = ports[sockx];
 1326             pq = 0;
 1327             status = pp->io[W_IN].p_status;
 1328             if( pp->p_EOF && (status & ST_WAITING) )
 1329                 continue;
 1330             if( status & ST_POLLRECV )
 1331                 pq |= PS_IN;
 1332             status = pp->io[W_OUT].p_status;
 1333             if( status & ST_POLLSEND )
 1334                 pq |= PS_OUT;
 1335             if( pq ){
 1336                 cactives[cactivex] = sockx;
 1337                 qfdv[cactivex] = pq;
 1338                 cactivex++;
 1339             }
 1340         }
 1341         nready = PollInsOuts(timeout,cactivex,cactives,qfdv,rfdv);
 1342 
 1343         if( nready < 0 ){
 1344             LE(LOG,"POLL ERROR: %d / %d\n",cactivex,activex);
 1345             dumpstat(fileno(LOG));
 1346             break;
 1347         }
 1348         if( nready == 0 )
 1349             fflush(LOG);
 1350 
 1351         for( px = 0; px < cactivex; px++ ){
 1352             sockx = cactives[px];
 1353             if( pp = ports[sockx] ){
 1354                 status = pp->io[W_OUT].p_status;
 1355 
 1356                 if( rfdv[px] & PS_OUT )
 1357                 if( status & ST_POLLSEND )
 1358                     clock1(sockx,W_OUT);
 1359             }
 1360         }
 1361         for( px = 0; px < cactivex; px++ ){
 1362             sockx = cactives[px];
 1363             if( pp = ports[sockx] ){
 1364                 status = pp->io[W_IN].p_status;
 1365 
 1366                 if( rfdv[px] & PS_IN )
 1367                 if( status & ST_POLLRECV )
 1368                     clock1(sockx,W_IN);
 1369             }
 1370         }
 1371         for( px = 0; px < cactivex; px++ ){
 1372             sockx = cactives[px];
 1373             if( pp = ports[sockx] ){
 1374                 if( rfdv[px] & PS_ERRORS ){
 1375                     LE(LOG,"[%x] POLL_ERROR (0x%x)\n",sockx,rfdv[px]);
 1376                     pp->p_EOF |= CLOSE_LOCALEOF;
 1377 /*
 1378  * immediate deletion of the vport here can be harmful:
 1379  *  connection reset cause (POLL_IN + POLL_HUP) on OSF/1
 1380  *  deleting the port without informing of remote peer if exists,
 1381  *  makes the remote port be dangling...
 1382  * thus this whole loop for PS_ERRORS should be after the loop for POLL_IN
 1383  */
 1384 if( pp->p_rport == 0 )
 1385 if( (pp->io[W_IN].p_status & ST_POLLRECV) == 0 )
 1386                     del_port(sockx);
 1387                 }
 1388             }
 1389         }
 1390         for( px = 0; px < cactivex; px++ ){
 1391             sockx = cactives[px];
 1392             if( pp = ports[sockx] ){
 1393                 status = pp->io[W_OUT].p_status;
 1394                 if( status & ST_POLLSEND )
 1395                 if( (qfdv[px] & PS_OUT) == 0 ){
 1396                     LD(LOG,"[%x] output from this phase.\n",sockx);
 1397                     clock1(sockx,W_OUT);
 1398                 }
 1399             }
 1400         }
 1401 
 1402         scanQwaiting();
 1403 
 1404         nac = ALIVEPORTS;
 1405         nai = 0;
 1406         for( sockx = 0; sockx < NUMPORTS && nai < nac; sockx++ ){
 1407             if( ports[sockx] == 0 )
 1408                 continue;
 1409             nai++;
 1410 
 1411             if( pp = ports[sockx] )
 1412             if( pp->io[W_IN].p_status == ST_RESOLV )
 1413             if( nready == 0 )
 1414                 clock1(sockx,W_IN);
 1415 
 1416             if( pp = ports[sockx] )
 1417             if( pp->io[W_IN].p_status == ST_RECV )
 1418 /*
 1419             if( pp->p_connected )
 1420 */
 1421 if( pp->p_connected || pp->p_invoked )
 1422                 if( 0 < pp->io[W_IN].p_rwcc ){
 1423 if( nready == 0 )
 1424 fprintf(LOG,"## ERROR: [%x] SOULD DO TIE BREAK %d\n",sockx,pp->io[W_IN].p_rwcc);
 1425                     relay(pp->p_lport,pp->p_dstsock,0);
 1426                 }
 1427 
 1428             if( pp = ports[sockx] )
 1429             if( pp->io[W_IN].p_status & ST_WAITING )
 1430             if( !inQwaiting(sockx) ){
 1431 fprintf(LOG,"## ERROR: [%x] not in Q %s\n",sockx,ss(pp->io[W_IN].p_status));
 1432 dumpstat(fileno(LOG));
 1433 exit(1);
 1434             }
 1435 
 1436             if( pp = ports[sockx] )
 1437             if( pp->io[W_OUT].p_status != ST_SEND )
 1438             if( pp->p_closing )
 1439                 del_port(sockx);
 1440 
 1441             if( pp = ports[sockx] )
 1442             if( pp->io[W_IN].p_status == ST_INIT )
 1443             if( pp->io[W_IN].p_rwcc == 0 )
 1444             if( server )
 1445             if( 1 <= time(NULL) - pp->p_ctime ){
 1446                 try_identify(pp,W_IN);
 1447             }
 1448 
 1449             if( pp = ports[sockx] )
 1450             if( pp->io[W_OUT].p_status == ST_CONNECT )
 1451             if( 10 <= time(NULL) - pp->p_ctime ){
 1452                 LE(LOG,"[%x] connection timeout (%s:%d)\n",
 1453                     sockx,pp->p_dsthost,pp->p_dstport);
 1454                 notifyEOF(pp);
 1455                 del_port(sockx);
 1456             }
 1457         }
 1458         if( router == NULL && server != NULL )
 1459         if( prefetched < 1 )
 1460         if( 0 <= prefetch("prefetch",-1,server_host,server_port) )
 1461             prefetched++;
 1462     }
 1463 }
 1464 
 1465 static int notify_connected(IOPORT *PP,int dsock)
 1466 {   int len,wcc;
 1467     CStr(msg,256);
 1468 
 1469     if( P_PROTO == P_SOCKS4 ){
 1470 LD(LOG,"[%x] notify SOCKS4 connected: %d\n",PP->p_lport,dsock);
 1471         msg[0] = 4;
 1472         msg[1] = 90;
 1473         msg[2] = 0; msg[3] = 0; msg[4] = 0; msg[5] = 0;
 1474         msg[6] = 0; msg[7] = 0;
 1475         len = 8;
 1476     }else
 1477     if( P_PROTO == P_BSOCKS ){
 1478         return 0;
 1479     }else
 1480     if( P_PROTO == P_TBSOCKS ){
 1481         return 0;
 1482     }else{
 1483         return 0;
 1484     }
 1485 
 1486     putMSG(PP->p_lport,msg,len);
 1487     return 0;
 1488 }
 1489 
 1490 static int relay(int src,int dst,int rwccoff)
 1491 {   IOPORT *sp,*dp,*lp;
 1492     int rleng; /* size of data left in the input buffer */
 1493     int ihlen; /* size of header in the input buffer */
 1494     int ohlen; /* size of header in the output buffer */
 1495     const char *ibuff;
 1496     int dsock;
 1497     int pleng,oleng,cleng;
 1498     int control,ctlarg;
 1499     int rport,lport;
 1500     int portid;
 1501     int packid;
 1502     int flagment,incomplete;
 1503 
 1504     sp = ports[src];
 1505     if( sp == NULL )
 1506         return 0;
 1507 
 1508     ibuff = sp->io[W_IN].p_buff;
 1509     rleng = sp->io[W_IN].p_rwcc;
 1510     cleng = rleng;
 1511     pleng = -1;
 1512     oleng = -1;
 1513     ihlen = 0;
 1514     ohlen = 0;
 1515     dsock = dst;
 1516     rport = 0;
 1517     control = 0;
 1518     ctlarg = 0;
 1519     incomplete = 0;
 1520 
 1521     ((char*)ibuff)[rleng] = 0;
 1522 
 1523     if( sp->p_proto == P_BSOCKS ){
 1524         if( rleng == 0 && sp->p_EOF ){
 1525             LE(LOG,"[%x] BSOCKS closed\n",src);
 1526             sp->p_closing |= CLOSE_BUSEOF;
 1527             return 0;
 1528         }
 1529         ihlen = getPackHead(src,ibuff,rleng,
 1530             &rport,&portid,&packid,&pleng,&control,&ctlarg);
 1531 
 1532         if( ihlen == -1 ){
 1533             if( !sp->p_EOF ){
 1534                 LD(LOG,"[%x] INCOMPLETE HEADER\n",src);
 1535                 return 0;
 1536             }else{
 1537                 ihlen = 0;
 1538                 oleng = rleng;
 1539                 goto EXIT;
 1540             }
 1541         }
 1542         ibuff += ihlen;
 1543         cleng = rleng - ihlen;
 1544 
 1545         if( flagment = sp->io[W_IN].p_flagment )
 1546             pleng = flagment;
 1547         
 1548         if( 0 <= pleng && cleng < pleng ){
 1549             LD(LOG,"[%x] PK incomplete %x/%x (%s)\n",
 1550                 src,cleng,pleng,
 1551                 ss(sp->io[W_IN].p_status));
 1552             if( control & CTL_DATA
 1553  /* && the destination port does not have multiple sources like BSOCKS */ ){
 1554                 incomplete = HEADSIZE;
 1555                 sp->io[W_IN].p_flagment = pleng - cleng;
 1556                 pleng = cleng;
 1557             }else{  
 1558                 sp->io[W_IN].p_status = ST_RECV;
 1559                 return 0;
 1560             }
 1561         }else{
 1562             sp->io[W_IN].p_flagment = 0;
 1563             numPackRECV++;
 1564         }
 1565         if( control & CTL_HELLO ){
 1566             LE(LOG,"[%x] RECV HELO BSOCKS/%s\n",src,ibuff);
 1567             oleng = pleng;
 1568             goto EXIT;
 1569         }
 1570         if( control & CTL_CONNECTDO ){
 1571 LD(LOG,"####[%x] [%s:%d]\n",src,sp->p_bhost,sp->p_bport);
 1572             connectFromBSOCKS(src,rport,ctlarg,ibuff,cleng);
 1573             oleng = pleng;
 1574             goto EXIT;
 1575         }
 1576 
 1577         if( portid == 0 )
 1578             portid = findLocalPort(rport);
 1579         lport = dePortID(portid);
 1580 
 1581         if( lport < 0 ){
 1582             /* notify the obsoletion to the peer ? */
 1583             oleng = pleng;
 1584             goto EXIT;
 1585         }
 1586         dsock = lport;
 1587         lp = ports[lport];
 1588         if( lp->p_rport == 0 ){
 1589             lp->p_rport = rport;
 1590 LD(LOG, "[%x] PORT ASSOCIATED R=%x/L=%x\n",src,rport,portid);
 1591         }
 1592         if( control & CTL_CONNECTING ){
 1593 LD(LOG,"[%x] RECV CONNECTING R=%x/L=%x\n",src,rport,portid);
 1594             if( OBUFSIZE < ctlarg )
 1595                 ctlarg = OBUFSIZE;
 1596             lp->p_rbuff = ctlarg;
 1597             lp->p_invoked = 1;
 1598             lp->io[W_IN].p_status = ST_RECV;
 1599             oleng = pleng; goto EXIT;
 1600         }
 1601         if( control & CTL_CONNECTED ){
 1602 LD(LOG,"[%x] RECV CONNECTED. R=%x/L=%x BUFFSIZE=0x%x\n",
 1603 sp->p_lport,rport,portid,ctlarg);
 1604             if( OBUFSIZE < ctlarg )
 1605                 ctlarg = OBUFSIZE;
 1606             lp->p_rbuff = ctlarg;
 1607             lp->p_connected = 1;
 1608             lp->io[W_IN].p_status = ST_RECV;
 1609             oleng = pleng; goto EXIT;
 1610         }
 1611         if( control & CTL_ACCEPTED ){
 1612 LD(LOG,"[%x] RECV ACCEPTED. R=%x/L=%x BUFFSIZE=0x%x\n",
 1613 sp->p_lport,rport,portid,ctlarg);
 1614         }
 1615         if( control & CTL_SENT ){
 1616 LD(LOG,"[%x] RECV SENT #%d %d/%d(%d) -> R=%x/L=%x\n",
 1617 src,packid,lp->io[W_IN].p_remotetotal,lp->io[W_IN].p_iototal,
 1618 outstanding(lp),rport,portid);
 1619             lp->io[W_IN].p_remotetotal = ctlarg;
 1620             oleng = pleng; goto EXIT;
 1621         }
 1622         if( control & CTL_DATA ){
 1623         }
 1624 
 1625         if( !incomplete )
 1626         if( control & (CTL_CONNERR|CTL_EOF) ){
 1627             lp->p_closing |= CLOSE_REMOTEPEER;
 1628 LD(LOG,"[%x] remote[%x] %s, status=IN[%s] OUT[%s,%d/%d]\n",
 1629 dsock,lp->p_rport,sctl(control),
 1630 ss(lp->io[W_IN].p_status),
 1631 ss(lp->io[W_OUT].p_status),
 1632 lp->io[W_OUT].p_rwcc,lp->io[W_OUT].p_bleng);
 1633             if( pleng == 0 ){
 1634                 oleng = pleng; goto EXIT;
 1635             }
 1636         }
 1637     }
 1638     if( 0 <= pleng )
 1639         oleng = pleng;
 1640     else    oleng = cleng;
 1641 
 1642     dp = ports[dsock];
 1643     if( dp == NULL ){
 1644         LD(LOG,"[%x] IGNORE relay to bogus port #%x (%d)\n",
 1645             src,dsock,oleng);
 1646         goto EXIT;
 1647     }
 1648     if( waitFlushed(sp,oleng) ){
 1649         /* wait until enough amount of output is flushed */
 1650         return 0;
 1651     }else
 1652     if( dp->io[W_OUT].p_status != ST_READY ){
 1653         int bleng = dp->io[W_OUT].p_bleng;
 1654         int rwcc = dp->io[W_OUT].p_rwcc;
 1655         int hsize;
 1656 
 1657         if( dp->p_proto == P_BSOCKS )
 1658             hsize = HEADSIZE;
 1659         else    hsize = 0;
 1660         
 1661 if( oleng == 0 )
 1662 LE(LOG,"#### ERROR? [%x]->%x SEND 0 ? control=%s\n",
 1663 src,dsock,sctl(control));
 1664 
 1665         if( bleng+hsize+oleng < OBUFSIZE ){
 1666             if( 0 < bleng )
 1667             LD(LOG,"[%x] add output (%x+%x >> %x/%x)\n",
 1668                 dp->p_lport,hsize,oleng,rwcc,bleng);
 1669         }else
 1670         if( sp->p_proto == P_BSOCKS
 1671         && (bleng-rwcc+hsize+oleng) <= OBUFSIZE ){
 1672             if( OBUFSIZE < bleng+hsize+oleng )
 1673                 shift_buff(dp);
 1674         }else{
 1675             sp->io[W_IN].p_waitdst = dsock;
 1676             sp->io[W_IN].p_waitingcc = ihlen+oleng;
 1677             sp->io[W_IN].p_status = ST_WAIT_SEND;
 1678             enQwaiting(sp->p_lport);
 1679             sp->io[W_IN].p_pendingcc = pleng;
 1680             sp->io[W_IN].p_pendingto = dsock;
 1681             return 0;
 1682         }
 1683     }
 1684     sp->io[W_IN].p_pendingcc = 0;
 1685     sp->io[W_IN].p_pendingto = 0;
 1686 
 1687     if( dp->p_proto == P_BSOCKS ){
 1688         CStr(msg,256);
 1689         ohlen = putPackHead(msg,sp,oleng,CTL_DATA,oleng);
 1690         bcopy(msg,(char*)dp->io[W_OUT].p_buff+dp->io[W_OUT].p_bleng,ohlen);
 1691         dp->io[W_OUT].p_bleng += ohlen;
 1692         dp->io[W_OUT].p_pktotal += ohlen;
 1693     }
 1694 
 1695     putMSG(dp->p_lport,ibuff,oleng);
 1696 
 1697 EXIT:
 1698     if( incomplete ){
 1699         sp->io[W_IN].p_rwcc = incomplete;
 1700         sp->io[W_IN].p_pktotal += oleng;
 1701     }else{
 1702         sp->io[W_IN].p_pkcount += 1;
 1703         sp->io[W_IN].p_pktotal += ihlen+oleng;
 1704 
 1705 /*
 1706 if(rleng-(ihlen+oleng))
 1707 LE(LOG,"[%x] relay bcopy(%d)\n",src,rleng-(ihlen+oleng));
 1708 */
 1709 
 1710         bcopy(sp->io[W_IN].p_buff+(ihlen+oleng),
 1711             (char*)sp->io[W_IN].p_buff,rleng-(ihlen+oleng));
 1712         sp->io[W_IN].p_rwcc -= (ihlen+oleng);
 1713     }
 1714     sp->io[W_IN].p_status = ST_RECV;
 1715 
 1716     if( 3 < dbglev ){
 1717         CStr(msg,0x1000);
 1718         sprintf(msg,"[%d] PK_FORW %d+%d %d(%s)[%d]%d -> ",src,
 1719             ohlen,oleng,src,
 1720             ss(sp->io[W_IN].p_status),
 1721             sp->io[W_IN].p_pkcount, ihlen+rleng);
 1722         if( dp = ports[dsock] )
 1723             Xsprintf(TVStr(msg),"(%d)%d(%s/%d)[%d]%d",dst,dsock,
 1724             ss(dp->io[W_OUT].p_status),dp->io[W_OUT].p_bleng,
 1725             dp->io[W_OUT].p_pkcount,ohlen+oleng);
 1726         else    Xsprintf(TVStr(msg),"NULL(%d)",dst);
 1727         LD(LOG,"%s\n",msg);
 1728     }
 1729 
 1730     if( sp->io[W_IN].p_rwcc < 0 ){
 1731         LD(LOG,"[%x] NEGATIVE RWCC %d\n",src,sp->io[W_IN].p_rwcc);
 1732         exit(-1);
 1733     }
 1734     if( !incomplete && sp->io[W_IN].p_rwcc )
 1735         relay(src,dst,0);
 1736     return 1;
 1737 }
 1738 static void putMSG(int dsock,PCStr(buff),int len)
 1739 {   PORT *op;
 1740 
 1741     if( len == 0 )
 1742         return;
 1743     op = &ports[dsock]->io[W_OUT];
 1744     bcopy(buff,(char*)op->p_buff+op->p_bleng,len);
 1745     op->p_bleng += len;
 1746     op->p_status = ST_SEND;
 1747     op->p_pkcount += 1;
 1748     op->p_pktotal += len;
 1749 }
 1750 
 1751 static int putPackHead(char msg[],IOPORT *pp,int leng,int control,int ctlarg)
 1752 {   int hleng;
 1753     int32 pack[8]; /**/
 1754     int pi;
 1755 
 1756     if( pp->p_EOF ){
 1757         control |= CTL_EOF;
 1758         pp->p_sentEOF = 1;
 1759     }
 1760 
 1761     PACKID++;
 1762     numPackSEND++;
 1763 
 1764     pack[M_CTLTYPE]  = control;
 1765     pack[M_CTLARG]   = ctlarg;
 1766     pack[M_SENDER]   = enPortID(pp);
 1767     pack[M_RECEIVER] = pp->p_rport;
 1768     pack[M_PACKID]   = PACKID;
 1769     pack[M_PACKLENG] = leng;
 1770     for( pi = 0; pi < M_PACKSIZE; pi++ )
 1771         pack[pi] = htonL(pack[pi]);
 1772     hleng = HEADSIZE;
 1773     bcopy(pack,msg,hleng);
 1774 
 1775 LD(LOG,"[%x] PK_SEND %s/%x R=%x<L=%x ID=%d LENG=%x/%x\n",
 1776 pp->p_lport, sctl(control),ctlarg,
 1777 pp->p_rport,enPortID(pp), PACKID,leng,hleng+leng);
 1778 
 1779     return hleng;
 1780 }
 1781 
 1782 static int getPackHead(int src,PCStr(msg),int rleng,int *rport,int *portid,int *packid,int *pleng,int *control,int *ctlarg)
 1783 {   int32 pack[8]; /**/
 1784     int pi;
 1785 
 1786     if( rleng < HEADSIZE )
 1787         return -1;
 1788 
 1789     bcopy(msg,pack,HEADSIZE);
 1790     for( pi = 0; pi < M_PACKSIZE; pi++ )
 1791         pack[pi] = ntohL(pack[pi]);
 1792     *control = pack[M_CTLTYPE];
 1793     *ctlarg  = pack[M_CTLARG];
 1794     *rport   = pack[M_SENDER];
 1795     *portid  = pack[M_RECEIVER];
 1796     *packid  = pack[M_PACKID];
 1797     *pleng   = pack[M_PACKLENG];
 1798 
 1799 LD(LOG,"[%x] PK_RECV %s/%x R=%x>L=%x ID=%d LENG=%x\n",
 1800 src, sctl(*control),*ctlarg, *rport,*portid, *packid,*pleng);
 1801 
 1802     return HEADSIZE;
 1803 }
 1804 
 1805 static void putCntrlMSG(IOPORT *bp,IOPORT *lp,int cntrl,int ctlarg)
 1806 {   CStr(msg,128);
 1807     int len;
 1808 
 1809     if( bp == NULL ){
 1810 fprintf(LOG,"## ERROR: [%x] putCntrlMSG(NULL) BSOCKS closed ?\n",lp->p_lport);
 1811         return;
 1812     }
 1813     len = putPackHead(msg,lp,0,cntrl,ctlarg);
 1814     putMSG(bp->p_lport,msg,len);
 1815 }
 1816 static void genCntrlMSG(int bsock,int rport,int control,int ctlarg)
 1817 {   IOPORT lb;
 1818 
 1819     lb.p_lport = 0;
 1820     lb.p_portid = 0;
 1821     lb.p_rport = rport;
 1822     putCntrlMSG(ports[bsock],&lb,control,ctlarg);
 1823 }
 1824 static void ackBSOCKS(IOPORT *pp,PCStr(ver))
 1825 {   CStr(msg,256);
 1826     CStr(hello,128);
 1827     int hlen,blen;
 1828     CStr(srchost,256);
 1829 
 1830     getpeerName(pp->p_lport,AVStr(srchost),"%A:%P");
 1831     LE(LOG,"[%x] ThruWay from %s\n",enPortID(pp),srchost);
 1832 
 1833 LD(LOG,"[%x] RETN HELO BSOCKS/%s connected, peer/%s\n",
 1834 pp->p_lport,BSOCKS_VER,ver);
 1835     sprintf(hello,"%s",BSOCKS_VER);
 1836     blen = strlen(hello) + 1;
 1837     hlen = putPackHead(msg,pp,blen,CTL_HELLO,OBUFSIZE);
 1838     Xstrcpy(DVStr(msg,hlen),hello);
 1839     putMSG(pp->p_lport,msg,hlen+blen);
 1840     LD(LOG,"[%x] SENT HELO BSOCKS %s\n",pp->p_lport,msg);
 1841 }
 1842 static void shift_buff(IOPORT *dp)
 1843 {   int bleng,rwcc;
 1844 
 1845     if( 0 < (rwcc = dp->io[W_OUT].p_rwcc) ){
 1846         refQStr(buff,dp->io[W_OUT].p_buff); /**/
 1847         buff  = (char*)dp->io[W_OUT].p_buff;
 1848         bleng = dp->io[W_OUT].p_bleng;
 1849         Bcopy(buff+rwcc,buff,bleng-rwcc);
 1850         dp->io[W_OUT].p_bleng -= rwcc;
 1851         dp->io[W_OUT].p_rwcc = 0;
 1852     }
 1853 }
 1854 
 1855 static void set_connected(int ssock,int dsock)
 1856 {   IOPORT *pp;
 1857 
 1858     pp = ports[ssock];
 1859     if( pp->p_srcsock == 0 ){
 1860         /*LD(LOG,"[%x] first (default) connection\n",ssock);*/
 1861         pp->p_srcsock = dsock;
 1862         pp->p_dstsock = dsock;
 1863         pp->io[W_IN].p_status  = ST_RECV;
 1864         pp->io[W_OUT].p_status = ST_READY;
 1865         notify_connected(pp,dsock);
 1866     }else{
 1867         /*LD(LOG,"[%x] second connection\n",ssock);*/
 1868     }
 1869 /*
 1870     if( ports[dsock]->p_proto == P_BSOCKS )
 1871         pp->io[W_IN].p_status = ST_RCONNECT;
 1872 */
 1873 }
 1874 
 1875 static void set_BUSBUF(int bsock){
 1876     PORT *ip = &ports[bsock]->io[W_IN];
 1877     free((char*)ip->p_buff);
 1878     setQStr(ip->p_buff,(char*)malloc(OBUFSIZE),OBUFSIZE);
 1879     ip->p_bsize = OBUFSIZE;
 1880 }
 1881 
 1882 #define NB_RETRY(errno) \
 1883     (errno==EINPROGRESS||errno==EWOULDBLOCK||errno==EALREADY||errno==EAGAIN)
 1884 
 1885 static int connError(PCStr(where),int sock,PCStr(host),int port,int _errno)
 1886 {
 1887     if( sock < 0 )
 1888         return 1;
 1889     if( NB_RETRY(_errno) )
 1890         return 0;
 1891     if( IsConnected(sock,NULL) )
 1892         return 0;
 1893 
 1894     LE(LOG,"[%x] %s connect(%s:%d) ERRNO=%d\n",sock,where,host,port,_errno);
 1895     return 1;
 1896 }
 1897 static int try_connect(int dsock)
 1898 {   int ssock;
 1899     IOPORT *sp,*dp;
 1900     IOPORT *PP;
 1901     int errno_sav;
 1902     int rcode;
 1903     const char *host;
 1904     int port;
 1905     CStr(callback,128);
 1906 
 1907     dp = ports[dsock];
 1908 
 1909     if( *ports[dsock]->p_bhost && ports[dsock]->p_bport){
 1910         int bsock;
 1911 
 1912         host = ports[dsock]->p_bhost;
 1913         port = ports[dsock]->p_bport;
 1914         bsock = findBSOCKS(host,port);
 1915         if( 0 <= bsock ){
 1916             connectAtRemote(bsock,ports[dsock]->p_srcsock);
 1917             return 0;
 1918         }
 1919     }else{
 1920         host = ports[dsock]->p_dsthost;
 1921         port = ports[dsock]->p_dstport;
 1922     }
 1923     ssock = ports[dsock]->p_srcsock;
 1924     PP = ports[ssock];
 1925     enQactive(dsock);
 1926 
 1927     errno = 0;
 1928     rcode = __connectServer(dsock,"Socket","BSOCK",host,port /*,1*/);
 1929     errno_sav = errno;
 1930     if( connError("try_connect",dsock,dp->p_dsthost,dp->p_dstport,errno) ){
 1931         del_port(dsock);
 1932         return -1;
 1933     }
 1934     LD(LOG,"[%x] connect(%d,%s:%d) = %d %d\n",
 1935     dp->p_srcsock,dsock,dp->p_dsthost,dp->p_dstport,rcode,errno_sav);
 1936 
 1937     if( NB_RETRY(errno_sav) ){
 1938         ports[dsock]->io[W_OUT].p_status = ST_CONNECT;
 1939         notify_connectingR(dsock,errno_sav);
 1940         return 0;
 1941     }
 1942 
 1943     if( IsConnected(dsock,NULL) )
 1944         rcode = 0;
 1945     else{
 1946         LE(LOG,"[%x] CONNECTION ERROR %s:%d\n",dsock,
 1947             dp->p_dsthost,dp->p_dstport);
 1948         rcode = -1;
 1949     }
 1950 
 1951     if( rcode == 0 ){
 1952         numConnect++;
 1953         ports[dsock]->p_srcsock = ssock;
 1954         ports[dsock]->p_dstsock = ssock;
 1955         ports[dsock]->io[W_IN].p_status  = ST_RECV;
 1956         ports[dsock]->io[W_OUT].p_status = ST_READY;
 1957         /* if not multiplex protocol */
 1958 
 1959         if( *ports[dsock]->p_bhost && ports[dsock]->p_bport ){
 1960             CStr(buff,1024);
 1961 
 1962             setsockbuf(dsock,BSOCKBUFSIZE,BSOCKBUFSIZE);
 1963             set_nodelay(dsock,1);
 1964             set_BUSBUF(dsock);
 1965 sprintf(callback,"%s:%d",Svhost0,svport0);
 1966             sprintf(buff,"BSOCKS/%s %s\r\n",BSOCKS_VER,callback);
 1967 LE(LOG,"[%x] SEND HELO BSOCKS/%s connect\n",dsock,BSOCKS_VER);
 1968             putMSG(dsock,buff,strlen(buff));
 1969             ports[dsock]->p_proto = P_BSOCKS;
 1970             set_connected(ssock,dsock);
 1971             connectAtRemote(dsock,ssock);
 1972         }else{
 1973             setsockbuf(dsock,IBUFSIZE,OBUFSIZE);
 1974             set_connected(ssock,dsock);
 1975             notify_connectedR(dsock,errno_sav);
 1976             if( ports[ssock]->io[W_IN].p_rwcc ){
 1977                 LD(LOG,"[%x] FLUSH INITIAL INPUT (%d)->[%d]\n",
 1978                     ssock,PP->io[W_IN].p_rwcc,dsock);
 1979                 relay(ssock,dsock,0);
 1980             }
 1981         }
 1982     }else
 1983     if( rcode < 0 ){
 1984         if( ports[ssock]->p_proto == P_BSOCKS ){
 1985             LE(LOG,"[%x] should close RPORT=%d\n",
 1986                 dsock,ports[dsock]->p_rport);
 1987             ports[dsock]->p_closing |= CLOSE_CONNERROR;
 1988             ports[dsock]->p_EOF |= CLOSE_CONNERROR;
 1989             relay(dsock,ssock,0);
 1990         }else{
 1991             del_port(ssock);
 1992             del_port(dsock);
 1993         }
 1994     }else{
 1995         ports[dsock]->io[W_OUT].p_status = ST_CONNECT;
 1996         notify_connectingR(dsock,errno_sav);
 1997     }
 1998     return 0;
 1999 }
 2000 
 2001 /*
 2002  *  request connection at remote router
 2003  */
 2004 static void connectAtRemote(int bsock,int ssock)
 2005 {   IOPORT *pp;
 2006     CStr(cmd,256);
 2007     CStr(msg,OBUFSIZE*2);
 2008     int hleng,cleng,bleng;
 2009 
 2010     pp = ports[ssock];
 2011     sprintf(cmd,"%s:%d\r\n",pp->p_dsthost,pp->p_dstport);
 2012     cleng = strlen(cmd);
 2013     bleng = pp->io[W_IN].p_rwcc;
 2014 
 2015     hleng = putPackHead(msg,pp,cleng+bleng,CTL_CONNECTDO,OBUFSIZE);
 2016     bcopy(cmd,msg+hleng,cleng);
 2017     bcopy(pp->io[W_IN].p_buff,msg+hleng+cleng,bleng);
 2018     msg[hleng+cleng+bleng] = 0;
 2019 
 2020     putMSG(bsock,msg,hleng+cleng+bleng);
 2021     set_connected(ssock,bsock);
 2022     pp->p_connectingR = 1;
 2023 
 2024 pp->p_rbuff = 4096; /* default buffer size */
 2025 
 2026     if( bleng ){
 2027         pp->io[W_IN].p_rwcc = 0;
 2028 /*
 2029         pp->io[W_IN].p_status = ST_RCONNECT;
 2030 */
 2031 LD(LOG,"[%x] PREFECHED REQUEST %x %x\n",pp->p_lport,bleng,
 2032 ports[bsock]->io[W_OUT].p_bleng);
 2033     }else{
 2034         if( 32 < time(NULL) - pp->p_ctime ){
 2035 LD(LOG,"[%x] ## EMPTY REQUEST BUFFER: TIMEOUT\n",pp->p_lport);
 2036             pp->p_closing = CLOSE_INITERROR;
 2037         }else
 2038 LD(LOG,"[%x] ## EMPTY REQUEST BUFFER\n",pp->p_lport);
 2039     }
 2040 }
 2041 static void connectFromBSOCKS(int bsock,int rport,int rbuff,PCStr(cmd),int clen)
 2042 {   CStr(host,512);
 2043     int port;
 2044     CStr(bhost,512);
 2045     int bport;
 2046     int dsock;
 2047     int errno_sav;
 2048     IOPORT *pp,*bp;
 2049     const char *ep;
 2050     int mleng;
 2051 
 2052     if( OBUFSIZE < rbuff )
 2053         rbuff = OBUFSIZE;
 2054 
 2055     init_bhostport(AVStr(bhost),&bport);
 2056     Xsscanf(cmd,"%[^:]:%d/%[^:]:%d",AVStr(host),&port,AVStr(bhost),&bport);
 2057 
 2058     errno = 0;
 2059     if( 100000 <= port ){
 2060         CStr(spec,128);
 2061         dsock = Socket1("bsocks",-1,"inet","tcp","bsocks", VStrNULL,0,
 2062             NULL,0, 0,NULL,0);
 2063         LD(LOG,"[%x] stab descriptor for remote ACCEPT\n",dsock);
 2064         if( 0 <= dsock ){
 2065             new_port("FromBSOCKS",bsock,dsock);
 2066             pp = ports[dsock];
 2067             strcpy(pp->p_dsthost,host);
 2068             pp->p_accport = port;
 2069         }
 2070         sprintf(spec,"%s:%d:%d",host,port-100000,1);
 2071         findASOCK(spec,dsock);
 2072     }else
 2073     dsock = newsocket("FromBSOCKS",bsock,host,port);
 2074     errno_sav = errno;
 2075     if( dsock < 0 ){
 2076         genCntrlMSG(bsock,rport,CTL_CONNERR,0);
 2077         return;
 2078     }
 2079     pp = ports[dsock];
 2080     pp->p_rport = rport;
 2081     pp->p_rbuff = rbuff;
 2082     pp->p_srcsock = bsock;
 2083     pp->p_dstsock = bsock;
 2084     if( bhost[0] && bport ){
 2085         strcpy(pp->p_bhost,bhost);
 2086         pp->p_bport = bport;
 2087     }
 2088     enQactive(dsock);
 2089 
 2090     if( clen && (ep = strchr(cmd,'\n')) ){
 2091         ep++;
 2092         mleng = clen - (ep - cmd);
 2093         if( 0 < mleng ){
 2094             bcopy(ep,(char*)pp->io[W_OUT].p_buff+pp->io[W_OUT].p_bleng,
 2095                 mleng);
 2096             pp->io[W_OUT].p_bleng += mleng;
 2097         }
 2098     }
 2099 
 2100     if( pp->p_accport ){
 2101         pp->io[W_IN].p_status = 0;
 2102         pp->io[W_OUT].p_status = ST_ACCEPT_WAIT;
 2103     }else
 2104     if( NB_RETRY(errno_sav) ){
 2105         ports[dsock]->io[W_OUT].p_status = ST_CONNECT;
 2106         notify_connectingR(dsock,errno_sav);
 2107     }else{
 2108         LD(LOG,"[%x] connected at the first trial.\n",dsock);
 2109         if( 0 < pp->io[W_OUT].p_bleng )
 2110             pp->io[W_OUT].p_status = ST_SEND;
 2111         else    ports[dsock]->io[W_OUT].p_status = ST_READY;
 2112         ports[dsock]->io[W_IN].p_status = ST_RECV;
 2113 
 2114         bp = ports[bsock];
 2115         RIDENT_send(dsock,bp->p_sockname,bp->p_peername,NULL);
 2116     }
 2117 }
 2118 /*
 2119  *  CONNECTING message
 2120  *  to the remote initiator can be ommitted and substituted by
 2121  *  CONNECTED message if the connection establised immediately.
 2122  */
 2123 static void notify_connectingR(int sock,int _errno)
 2124 {   IOPORT *pp,*bp;
 2125 /*
 2126     pp = ports[sock];
 2127     if( pp->p_rport && pp->p_connecting == 0 ){
 2128 LD(LOG,"[%x] SEND CONNECTING ->[%x]->[%x] errno=%d (%s:%d)\n",
 2129 sock,pp->p_dstsock,pp->p_rport,_errno,pp->p_dsthost,pp->p_dstport);
 2130         bp = ports[pp->p_srcsock];
 2131         putCntrlMSG(bp,pp,CTL_CONNECTING,OBUFSIZE);
 2132         pp->p_connecting = 1;
 2133     }
 2134 */
 2135 }
 2136 static void notify_connectedR(int sock,int _errno)
 2137 {   IOPORT *pp,*bp;
 2138 
 2139     pp = ports[sock];
 2140 /*
 2141     if( pp->p_rport ){
 2142 LD(LOG,"[%x] SEND CONNECTED -->[%x]->[%x] errno=%d (%s:%d)\n",
 2143 sock,pp->p_dstsock,pp->p_rport,_errno,pp->p_dsthost,pp->p_dstport);
 2144         bp = ports[pp->p_srcsock];
 2145         putCntrlMSG(bp,pp,CTL_CONNECTED,OBUFSIZE);
 2146     }
 2147 */
 2148     if( pp->io[W_OUT].p_bleng ){
 2149 LD(LOG,"[%x] FLUSH INITIAL OUTPUT (%d)\n",sock,pp->io[W_OUT].p_bleng);
 2150         pp->io[W_OUT].p_status = ST_SEND;
 2151     }
 2152 }
 2153 
 2154 static int try_identify(IOPORT *PP,int IO)
 2155 {   int proto;
 2156     int sockx;
 2157 
 2158     sockx = P_SOCK;
 2159     if( (proto = identify_protocol(PP,IO)) < 0 ){
 2160         PP->p_closing = CLOSE_INITERROR;
 2161         del_port(sockx);
 2162         return -1;
 2163     }
 2164     if( P_PROTO == 0 ) /* not yet identified */
 2165         return 0;
 2166 
 2167     if( proto == P_BSOCKS ){
 2168         setsockbuf(sockx,BSOCKBUFSIZE,BSOCKBUFSIZE);
 2169         set_nodelay(sockx,1);
 2170         P_STATUS = ST_RECV;
 2171     }else{
 2172         setsockbuf(sockx,IBUFSIZE,OBUFSIZE);
 2173         P_STATUS = ST_RESOLV;
 2174     }
 2175     return proto;
 2176 }
 2177 static void clock1(int sockx,int IO)
 2178 {   IOPORT *PP;
 2179     int clsock;
 2180     int ssock;
 2181     int rcc,wcc;
 2182     int errno_sav;
 2183     const char *host;
 2184     CStr(srchost,256);
 2185     int port;
 2186     CStr(sockname,256);
 2187     CStr(peername,256);
 2188     CStr(accepted,128);
 2189 
 2190     PP = ports[sockx];
 2191     if( PP == NULL )
 2192         return;
 2193 
 2194     switch( P_STATUS ){
 2195         case ST_ACCEPT:
 2196         clsock = ACCEPT(sockx,1,-1,0);
 2197         if( clsock < 0 && errno == EAGAIN ){
 2198             LD(LOG,"[%d] ST_ACCEPT retry lator ????\n",sockx);
 2199             return;
 2200         }
 2201 
 2202         setNonblockingIO(clsock,1);
 2203         numAccept++;
 2204 
 2205         getpairName(clsock,AVStr(sockname),AVStr(peername));
 2206         sprintf(accepted,"ACCEPTED %s %s\r\n",peername,sockname);
 2207 
 2208         if( ssock = ports[sockx]->p_accsock ){
 2209             IOPORT *sp = ports[ssock];
 2210             if( sp == 0 ){
 2211 LD(LOG,"[%x] ST_ACCEPT (remote) = %d < srcsock=%d ****DANGLING\n",
 2212 sockx,clsock,ssock);
 2213 /* DEQ */
 2214 ports[sockx]->p_closing = CLOSE_LOCALEOF;
 2215 close(clsock);
 2216                 break;
 2217             }
 2218             if( sp->p_accport ){
 2219                 IOPORT *bp;
 2220                 CStr(msg,128);
 2221                 int len,alen;
 2222 
 2223 LD(LOG,"[%x] ST_ACCEPT (remote) = %d < srcsock=%d\n",sockx,clsock,ssock);
 2224                 dup2(clsock,ssock);
 2225                 close(clsock);
 2226                 clsock = ssock;
 2227                 sp->io[W_OUT].p_status = ST_READY;
 2228                 sp->io[W_IN].p_status = ST_RECV;
 2229 
 2230 /* DEQ */
 2231 ports[sockx]->p_accsock = sp->p_acceptQ;
 2232 LD(LOG,"[%x] [%x] NEXT ACCEPT = %d\n",sockx,clsock,sp->p_acceptQ);
 2233 if( ports[sockx]->p_accsock == 0 )
 2234             ports[sockx]->p_closing |= CLOSE_LOCALEOF;
 2235 
 2236                 alen = strlen(accepted);
 2237                 bp = ports[sp->p_srcsock];
 2238             len = putPackHead(msg,sp,alen,CTL_ACCEPTED,OBUFSIZE);
 2239                 Xstrcpy(DVStr(msg,len),accepted);
 2240                 putMSG(bp->p_lport,msg,len+alen);
 2241                 break;
 2242             }
 2243         }
 2244 
 2245         new_port("ST_ACCEPT",sockx,clsock);
 2246         PP = ports[clsock];
 2247         P_STATUS = ST_INIT;
 2248         enQactive(clsock);
 2249 
 2250         {
 2251             CStr(sockname,256);
 2252             CStr(peername,256);
 2253             getpairName(clsock,AVStr(sockname),AVStr(peername));
 2254             PP->p_sockname = stralloc(sockname);
 2255             PP->p_peername = stralloc(peername);
 2256         }
 2257 
 2258         if( 1 < dbglev ){
 2259         getpeerName(clsock,AVStr(srchost),"%H:%P");
 2260         LD(LOG,"<%x>(%d) acc %s\n",PP->p_portid,ALIVEPORTS,srchost);
 2261         LD(LOG,"[%x] ST_ACCEPT = [%x] %s\n",sockx,clsock,srchost);
 2262         }
 2263         if( ssock = ports[sockx]->p_accsock ){
 2264             IOPORT *sp = ports[ssock];
 2265 
 2266             LE(LOG,"[%x] ACCEPTED [%x]->[%x]\n",sockx,clsock,ssock);
 2267 
 2268 /* DEQ */
 2269 ports[sockx]->p_accsock = sp->p_acceptQ;
 2270 LD(LOG,"[%x] [%x] NEXT ACCEPT = %d\n",sockx,clsock,sp->p_acceptQ);
 2271 if( ports[sockx]->p_accsock == 0 )
 2272             ports[sockx]->p_closing = CLOSE_LOCALEOF;
 2273 
 2274             PP->p_srcsock = ssock;
 2275             PP->p_dstsock = ssock;
 2276             PP->io[W_IN].p_status = ST_RECV;
 2277             PP->io[W_OUT].p_status = ST_READY;
 2278             sp->p_srcsock = clsock;
 2279             sp->p_dstsock = clsock;
 2280             sp->io[W_IN].p_status = ST_RECV;
 2281             sp->io[W_OUT].p_status = ST_SEND;
 2282 /*
 2283             getpeerName(clsock,srchost,"%A:%P");
 2284             sprintf(sp->io[W_OUT].p_buff,"ACCEPTED %s\r\n",srchost);
 2285 */
 2286             strcpy(sp->io[W_OUT].p_buff,accepted);
 2287             sp->io[W_OUT].p_bleng = strlen(sp->io[W_OUT].p_buff);
 2288         }
 2289         break;
 2290 
 2291         case ST_INIT:
 2292         errno = 0;
 2293         rcc = recv(sockx,(char*)P_BUFF+P_RWCC,P_REMCC,0);
 2294         errno_sav = errno;
 2295         LD(LOG,"[%x] ST_INIT = %d E=%d\n",sockx,rcc,errno_sav);
 2296 
 2297         if( rcc <= 0 ){
 2298             if( errno_sav == EWOULDBLOCK )
 2299                 break;
 2300             PP->p_EOF |= CLOSE_LOCALEOF;
 2301             del_port(sockx);
 2302             break;
 2303         }
 2304         if( 0 < rcc ){
 2305             P_IOTOTAL += rcc;
 2306             P_IOCOUNT += 1;
 2307         }
 2308         P_RWCC += rcc;
 2309         try_identify(PP,IO);
 2310         if( P_STATUS != ST_RESOLV )
 2311             break;
 2312 
 2313 
 2314     case ST_RESOLV:
 2315         RSLV_TIMEOUT = 0;
 2316         RSLV_TIMEDOUT = 0;
 2317         if( strcmp(P_DHOST,"*") != 0 )
 2318         if( gethostbyname(P_DHOST) == 0 ){
 2319 fprintf(LOG,"## ERROR: [%x] TIMEDOUT=%d %s\n",sockx,RSLV_TIMEDOUT,P_DHOST);
 2320             if( !RSLV_TIMEDOUT || 5 < ++PP->p_resfail
 2321              || !IsConnected(sockx,NULL) ){
 2322                 del_port(sockx);
 2323                 break;
 2324             }
 2325             LD(LOG,"[%x] %d RESOLVING DHOST=%s...\n",sockx,
 2326                 PP->p_resfail,P_DHOST);
 2327             P_STATUS = ST_RESOLV;
 2328             break;
 2329         }
 2330 
 2331         if( *P_BHOST && P_BPORT ){
 2332             int bsock;
 2333             bsock = findBSOCKS(P_BHOST,P_BPORT);
 2334             if( 0 < bsock ){
 2335                 connectAtRemote(bsock,sockx);
 2336                 break;
 2337             }
 2338         }
 2339         if( *P_BHOST && P_BPORT ){
 2340             host = P_BHOST;
 2341             port = P_BPORT;
 2342         }else{
 2343             host = P_DHOST;
 2344             port = P_DPORT;
 2345         }
 2346         errno = 0;
 2347         P_DSOCK = newsocket("ST_INIT",sockx,host,port);
 2348         if( P_DSOCK < 0 ){
 2349             LE(LOG,"[%x] connect error: %s:%d sock=%d errno=%d\n",
 2350                 P_DSOCK,host,port,P_DSOCK,errno);
 2351             del_port(sockx);
 2352             break;
 2353         }
 2354 
 2355         ports[P_DSOCK]->io[W_OUT].p_status = ST_CONNECT;
 2356         enQactive(P_DSOCK);
 2357 
 2358         ports[P_DSOCK]->p_srcsock = sockx;
 2359         ports[P_DSOCK]->p_dstsock = sockx;
 2360         strcpy(ports[P_DSOCK]->p_dsthost,P_DHOST);
 2361         ports[P_DSOCK]->p_dstport = P_DPORT;
 2362         strcpy(ports[P_DSOCK]->p_bhost,P_BHOST);
 2363         ports[P_DSOCK]->p_bport = P_BPORT;
 2364         ports[P_DSOCK]->p_rport = P_RPORT;
 2365         P_RPORT = 0;
 2366         /* should watch EOF before conection establied ... */
 2367 
 2368         P_STATUS = ST_RECV;
 2369         break;
 2370 
 2371         case ST_CONNECT:
 2372         LD(LOG,"[%x] ST_CONNECT ready (%s:%d)\n",sockx,P_DHOST,P_DPORT);
 2373         try_connect(sockx);
 2374         if( P_STATUS != ST_CONNECT )
 2375         if( RIDENT_SERVER ){
 2376             IOPORT *sp;
 2377             sp = ports[PP->p_srcsock];
 2378             RIDENT_send(sockx,sp->p_sockname,sp->p_peername,NULL);
 2379         }
 2380         if( P_STATUS != ST_SEND )
 2381             break;
 2382 
 2383         case ST_SEND:
 2384         numSEND++;
 2385 
 2386 if( P_REMCC <= 0 )
 2387 LD(LOG,"[%x]%sST_SEND(%x+%x/%x)E=%d (%x/%x) SEND EMPTY?\n",
 2388 sockx,P_PROTO==P_BSOCKS?"*":" ",
 2389 P_RWCC,0,P_REMCC,0, P_IOTOTAL,P_IOCOUNT);
 2390 
 2391         if( 0 < P_REMCC ){
 2392             errno = 0;
 2393             wcc = send(sockx,P_BUFF+P_RWCC,P_REMCC,0);
 2394             errno_sav = errno;
 2395 
 2396 LD(LOG,"[%x]%sST_SEND(%x+%x/%x)E=%d (%x/%x)\n",
 2397 sockx,P_PROTO==P_BSOCKS?"*":" ",
 2398 P_RWCC,wcc,P_REMCC,errno_sav, P_IOTOTAL,P_IOCOUNT);
 2399 
 2400             if( wcc <= 0 ){
 2401                 if( errno_sav == EWOULDBLOCK )
 2402                     break;
 2403 LD(LOG,"[%x] #### SIGPIPE L=%x>R=%x\n",sockx,enPortID(PP),P_RPORT);
 2404                 ssock = P_SSOCK;
 2405                 if( P_RPORT ){
 2406                     notifyEOF(PP);
 2407                     PP->p_EOF |= CLOSE_LOCALEOF;
 2408                 }
 2409                 del_port(sockx);
 2410                 del_port(ssock);
 2411                 break;
 2412             }else{
 2413                 P_IOTOTAL += wcc;
 2414                 P_IOCOUNT += 1;
 2415             }
 2416             P_RWCC += wcc;
 2417             notifyFlushed(PP,wcc);
 2418         }
 2419         if( P_REMCC == 0 ){
 2420             P_STATUS = ST_READY;
 2421             P_BUFLEN = 0;
 2422             P_RWCC = 0;
 2423 
 2424             if( ports[sockx]->p_closing )
 2425                 del_port(sockx);
 2426         }
 2427         break;
 2428 
 2429         case ST_RECV:
 2430         numRECV++;
 2431         if( P_REMCC == 0 ){
 2432             LD(LOG,"[%x] ST_RECV 0 (%x)\n",sockx,P_RWCC);
 2433             sleep(1);
 2434             relay(sockx,P_DSOCK,0);
 2435             break;
 2436         }
 2437 
 2438         errno = 0;
 2439         rcc = recv(sockx,(char*)P_BUFF+P_RWCC,P_REMCC,0);
 2440         errno_sav = errno;
 2441 
 2442 LD(LOG,"[%x]%sST_RECV(%x+%x/%x)E=%d (%x/%x)\n",
 2443 sockx,P_PROTO == P_BSOCKS?"*":" ",
 2444 P_RWCC,rcc,P_REMCC,errno_sav, P_IOTOTAL,P_IOCOUNT);
 2445 
 2446         if( rcc <= 0 ){
 2447             /* non-blocking read may return rcc=0,errno=0 ... */
 2448             if( errno_sav != EWOULDBLOCK )
 2449                 P_EOF |= CLOSE_LOCALEOF;
 2450             if( P_RWCC == 0 ){
 2451                 if( P_EOF ){
 2452                     notifyEOF(PP);
 2453                     del_port(P_SOCK);
 2454                 }
 2455                 break;
 2456             }
 2457             rcc = 0;
 2458         }else{
 2459             P_IOTOTAL += rcc;
 2460             P_IOCOUNT += 1;
 2461 
 2462             if( rcc < P_REMCC )
 2463             if( P_PROTO != P_BSOCKS )
 2464             if( P_IOTOTAL < 4096 )
 2465             if( PollIn(sockx,1) && Peek1(sockx) <= 0 ){
 2466                 LD(LOG,"[%x] EOF after 0x%x\n",sockx,rcc);
 2467                 P_EOF |= CLOSE_LOCALEOF;
 2468             }
 2469         }
 2470         if( 0 < rcc ){
 2471             P_RWCC += rcc;
 2472             setVStrEnd(P_BUFF,P_RWCC);
 2473         }
 2474 
 2475         relay(sockx,P_DSOCK,0);
 2476 
 2477         if( rcc <= 0
 2478          || PP->p_EOF && P_RWCC==0 && PP->io[W_OUT].p_bleng==0 ){
 2479             IOPORT *dp;
 2480 
 2481             PP->p_closing |= CLOSE_LOCALEOF;
 2482             if( (dp = ports[P_DSOCK]) && dp->p_proto != P_BSOCKS )
 2483                 dp->p_closing |= CLOSE_LOCALPEER;
 2484             break;
 2485         }
 2486         break;  
 2487     }
 2488 }
 2489 
 2490 static int waitFlushed(IOPORT *pp,int wcc)
 2491 {   int status;
 2492 
 2493     if( pp->p_proto == P_BSOCKS )
 2494         return 0;
 2495     if( ports[pp->p_srcsock]->p_proto != P_BSOCKS )
 2496         return 0;
 2497     if( pp->io[W_IN].p_rwcc == 0 )
 2498         return 0;
 2499 
 2500     status = pp->io[W_IN].p_status;
 2501     if( status == ST_WAIT_RFLUSH )
 2502         return 1;
 2503 
 2504     if( pp->p_rbuff < outstanding(pp)+wcc ){
 2505 LD(LOG,"[%x] SUSP %d BS=%x:%x\n",pp->p_lport,outstanding(pp),
 2506 OBUFSIZE,pp->p_rbuff);
 2507         pp->io[W_IN].p_waitwcc = wcc;
 2508         pp->io[W_IN].p_statussave = status;
 2509         pp->io[W_IN].p_status = ST_WAIT_RFLUSH;
 2510         enQwaiting(pp->p_lport);
 2511         numSUSP++;
 2512         return 1;
 2513     }
 2514     return 0;
 2515 }
 2516 static void pollFlushed(IOPORT *pp)
 2517 {   int status;
 2518     int wcc;
 2519 
 2520     wcc = pp->io[W_IN].p_waitwcc;
 2521     if( outstanding(pp)+wcc <= pp->p_rbuff ){
 2522 LD(LOG,"[%x] RESM %d L=%x/R=%x\n",
 2523 pp->p_lport,outstanding(pp),enPortID(pp),pp->p_rport);
 2524         status = pp->io[W_IN].p_status = pp->io[W_IN].p_statussave;
 2525         if( status == ST_RECV && pp->io[W_IN].p_rwcc ){
 2526             /* duplicate enQwaiting may occur .. */
 2527             relay(pp->p_lport,pp->p_dstsock,0);
 2528         }
 2529     }
 2530 }
 2531 static void notifyFlushed(IOPORT *pp,int wcc)
 2532 {   IOPORT *bp;
 2533     PORT *op;
 2534     int isize;
 2535 
 2536     if( pp->p_rport == 0 )
 2537         return;
 2538 
 2539     bp = ports[pp->p_srcsock];
 2540     if( bp == NULL )
 2541         return;
 2542 
 2543     op = &pp->io[W_OUT];
 2544 
 2545     if( pp->p_EOF ){
 2546         notifyEOF(pp);
 2547         return;
 2548     }
 2549     isize = op->p_iototal - op->p_notifiedcc;
 2550 
 2551     /* Reduce flow control messae to 1/10 or less ... */
 2552     /* the peer may be waiting for sending a large packet to write
 2553      * which size is full of buffer, thus when the buffer become
 2554      * empty, it must be informed anyway ???
 2555      */
 2556     if( /*op->p_rwcc < op->p_bleng &&*/ isize < OBUFSIZE/4 ){
 2557         Nn++;
 2558         return;
 2559     }else   Ni++;
 2560 
 2561     if( op->p_notifiedcc < op->p_iototal ){
 2562         putCntrlMSG(bp,pp,CTL_SENT,op->p_iototal);
 2563 
 2564 LD(LOG,"[%x] SEND SENT #%d %d/%d -> R=%x/L=%x (%d/%d/%s) INF=%d:IGN=%d\n",
 2565 pp->p_lport,PACKID,isize,op->p_iototal,
 2566 pp->p_rport,enPortID(pp),op->p_rwcc,op->p_bleng,ss(bp->io[W_OUT].p_status),
 2567 Ni,Nn);
 2568         op->p_notifiedcc = op->p_iototal;
 2569     }
 2570 }
 2571 
 2572 /*
 2573  * notify connection reset to the peer port at a remote router
 2574  */
 2575 static void notifyEOF(IOPORT *pp)
 2576 {   IOPORT *bp;
 2577 
 2578 LD(LOG,"[%x] notifyEOF R=%x B=[%s:%d] connectingR=%d\n",
 2579 pp->p_lport,pp->p_rport,pp->p_bhost,pp->p_bport,pp->p_connectingR);
 2580 
 2581     if( pp->p_rport == 0 )
 2582     if( pp->p_connectingR == 0 )
 2583         return;
 2584 
 2585     if( pp->p_sentEOF ){
 2586 fprintf(LOG,"[%x] ## don't send DUPLICATE EOF\n",pp->p_lport);
 2587         return;
 2588     }
 2589 
 2590     pp->p_sentEOF = 1;
 2591     bp = ports[pp->p_srcsock];
 2592     putCntrlMSG(bp,pp,CTL_EOF,0);
 2593 }