"Fossies" - the Fresh Open Source Software Archive

Member "delegate9.9.13/src/sox.c" (31 Oct 2014, 69138 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 "sox.c" see the Fossies "Dox" file reference documentation.

    1 const char *SIGN_sox_c="{FILESIGN=sox.c:20141031194212+0900:8f57bd71083c3ec7:Author@DeleGate.ORG:1YiHM0MKjYpoV/3cpoPrBeujKgQRmVt0fDoJ+hnMbdTFHKwu0+s5NSZwgJLyVXkiv5nEImt+9BpX6w+zi19u7R3qQISzmrISJTeaGLd7CPrR0hWVdvTjWCOx6ogWyp4bz5uBlEpT4vT+FKYaWj41a/R1fTOuQg5O/KV4g2vWO/o=}";
    2 
    3 /*////////////////////////////////////////////////////////////////////////
    4 Copyright (c) 2002-2008 National Institute of Advanced Industrial Science and Technology (AIST)
    5 AIST-Product-ID: 2000-ETL-198715-01, H14PRO-049, H15PRO-165, H18PRO-443
    6 
    7 Permission to use this material for noncommercial and/or evaluation
    8 purpose, copy this material for your own use, and distribute the copies
    9 via publicly accessible on-line media, without fee, is hereby granted
   10 provided that the above copyright notice and this permission notice
   11 appear in all copies.
   12 AIST MAKES NO REPRESENTATIONS ABOUT THE ACCURACY OR SUITABILITY OF THIS
   13 MATERIAL FOR ANY PURPOSE.  IT IS PROVIDED "AS IS", WITHOUT ANY EXPRESS
   14 OR IMPLIED WARRANTIES.
   15 /////////////////////////////////////////////////////////////////////////
   16 Content-Type:   program/C; charset=US-ASCII
   17 Program:    SockMux (socket multiplexer)
   18 Author:     Yutaka Sato <ysato@delegate.org>
   19 Description:
   20     Multiplex local sockets and tunnel to remote via a single
   21     bidrectional communication channel.
   22 
   23     Server binding:
   24     SERVER=proto[://server],-in  server for connection incoming from remote
   25 
   26 TODO:
   27  - SERVER="sockmux:shio:script.shio"
   28  - SERVER=proto[://server],-out server for outogoing
   29  - SERVER="proto[://server]-out(optionList):-:-Pxxxx"
   30  - substitute "CRON=..." parameter ?
   31 
   32  - resumable commin/commout for movile usage
   33  - multiple commin/commout with encryption or not
   34  - 7bit mode comm relayable over telnet
   35  - SockMux as hidden background exchange like Telnet commands
   36  - SockMux for FTP data-connections like MODE XDC
   37  - symbolic message version of SockMux
   38  - remote administration commands like SNMP
   39 
   40  - multiple queue with priority
   41  - give the highest priority to Telnet, the lowest one to FTP, etc.
   42  - QoS control
   43 
   44  - forwarding originator's (and forwarder's) identity in chained SockMux
   45  - forwarding originator's certificate (singed and verified, or encrypted)
   46  - C1 -> S <- C2 ... and C1 <-> C2, relay as a reflector
   47  - SENDME/IHAVE or CONNECT2vaddr + ACCEPTvaddr or SEND2vaddr+RECVvaddr
   48  - HELLO assoc-name
   49  - multicasting on SockMux, like ViaBus
   50 
   51  - UTF-8 encoding including header ?
   52 
   53 History:
   54     021215  created
   55 //////////////////////////////////////////////////////////////////////#*/
   56 #include <stdlib.h>
   57 #include <stdio.h>
   58 #include <errno.h>
   59 #include <fcntl.h>
   60 #include "vsocket.h"
   61 #include "vsignal.h"
   62 #include "ystring.h"
   63 #include "dglib.h"
   64 #include "credhy.h"
   65 #include "fpoll.h"
   66 #include "proc.h"
   67 #include "log.h"
   68 #include "file.h" /* dupclosed() */
   69 
   70 int isPrivateSox(DGC*ctx);
   71 int CTX_withAuth(DGC*ctx);
   72 int CTX_withYY(DGC*ctx);
   73 int CTX_withYY_SV(DGC*ctx);
   74 int CTX_withYY_CL(DGC*ctx);
   75 int CTX_withYY_BROKEN(DGC*ctx);
   76 int doAuth(DGC*ctx,AuthInfo *auth);
   77 int get_MYAUTH(DGC*ctx,PVStr(myauth),PCStr(proto),PCStr(dhost),int dport);
   78 
   79 extern int CHILD_SERNO;
   80 extern int NUM_CHILDREN;
   81 
   82 extern int ACC_TIMEOUT;
   83 extern int CFI_DISABLE;
   84 
   85 /*
   86  *  SIMPLE SOCKET TUNNELING MULTIPLEXER PROTOCOL
   87  *  Version: 0.3
   88  */
   89 #define MAJVER  0
   90 #define MINVER  3
   91 #define MYVER   ((MAJVER<<4) | MINVER)
   92 #define VERENC  0x80
   93 
   94 /*
   95  *  PROTOCOL SPECIFICATION
   96  */
   97 typedef unsigned char octet1;
   98 typedef struct {
   99     octet1  ph_ver; /* protocol version */
  100     octet1  ph_type; /* packet type */
  101     octet1  ph_Said[2]; /**//* sender's id */
  102     octet1  ph_Raid[2]; /**//* receiver's id */
  103     octet1  ph_leng[2]; /**//* payload length */
  104 } PackV03;
  105 #define PHSIZE  sizeof(PackV03)
  106 /*
  107 #define PWSIZE  512
  108 */
  109 #if isWindowsCE()
  110 #define PWSIZE  1024
  111 #else
  112 #define PWSIZE  16*1024
  113 #endif
  114 #define PBSIZE  (PWSIZE-PHSIZE)
  115 
  116 typedef struct SoxPacket {
  117     PackV03 p_head;
  118     MStr(   p_data,PWSIZE-PHSIZE);
  119 } Packet;
  120 
  121 /*
  122  *  PACKET TYPES
  123  */
  124 #define SOX_ACK     0x40
  125 #define SOX_NOOP    0x00 /* NO operation (for keep-alive) */
  126 #define SOX_HELLO   0x01 /* HELLO hostname */
  127 #define SOX_CONNECT 0x02 /* CONNECT bufsize client clif [bindif?] */
  128 #define SOX_CONNECT2    0x03 /* CONNECT TO ... specifying destination port */
  129 #define SOX_BIND    0x04
  130 #define SOX_ACCEPT  0x05
  131 #define SOX_SEND    0x06 /* SEND    L# R# data */
  132 #define SOX_SENDOOB 0x07 /* SENDOOB L# R# data */
  133 #define SOX_CLOSE   0x08 /* CLOSE   L# R# reason */
  134 #define SOX_ECHO    0x09
  135 #define SOX_SETOPT  0x0A
  136 #define SOX_GETOPT  0x0B
  137 #define SOX_CRYPTON 0x0C /* packets will be encrypted after this packet */
  138 #define SOX_OOBPUSH 0x0D
  139 #define SOX_UNBIND  0x0E
  140 
  141 #define SOX_HELLOOK (SOX_ACK|SOX_HELLO)   /* HELLOOK hostname */
  142 #define SOX_CONNECTED   (SOX_ACK|SOX_CONNECT) /* CONNECTED bufsize server svif */
  143 #define SOX_ECHOOK  (SOX_ACK|SOX_ECHO)
  144 #define SOX_SENT    (SOX_ACK|SOX_SEND)    /* SENT length */
  145 #define SOX_SENTOOB (SOX_ACK|SOX_SENDOOB) /* SENTOOB length */
  146 #define SOX_CLOSED  (SOX_ACK|SOX_CLOSE)   /* CLOSED reason */
  147 #define SOX_BINDOK  (SOX_ACK|SOX_BIND)
  148 
  149 /*
  150  * OPTIONS
  151  */
  152 #define SOX_O_CRYPT 0x01
  153 #define SOX_O_CONNDATA  0x02
  154 #define CRYPT_CREDHY    0x01
  155 #define CRYPT_DHKEY 0x01
  156 #define CRYPT_DHKEYX    0x00
  157 
  158 #define SOX_O_PACKSIZE  0x03
  159 #define SOX_O_AUTH  0x04
  160 #define AUTH_PASS   0x01
  161 
  162 /* internal status */
  163 #define SOX_COMMOUT 0x0100
  164 #define SOX_COMMIN  0x0200
  165 #define SOX_LISTEN  0x0300
  166 #define SOX_WAITING 0x1000 /* waiting remote, stop local input */
  167 #define SOX_SENDING (SOX_WAITING|SOX_SEND)
  168 #define SOX_SENDINGOOB  (SOX_WAITING|SOX_SENDOOB)
  169 #define SOX_PARENT  0x8000
  170 
  171 #define p_Ver   p_head.ph_ver
  172 #define p_Type  p_head.ph_type
  173 #define GET_INT16(a)    ((a[0]<<8)|a[1])
  174 /*
  175 #define SET_INT16(a,v)  {a[0] = v>>8; a[1] = v;}
  176 just to suppress the warning for setting Aid with only 8bits of "unsigned char"
  177 */
  178 #define SET_INT16(a,v)  {a[0] = ((int)(v))>>8; a[1] = v;}
  179 #define PK_Leng(p)  GET_INT16((p)->p_head.ph_leng)
  180 #define PK_setLeng(p,l) SET_INT16((p)->p_head.ph_leng,l)
  181 #define PK_Said(p)  GET_INT16((p)->p_head.ph_Said)
  182 #define PK_setSaid(p,l) SET_INT16((p)->p_head.ph_Said,l)
  183 #define PK_Raid(p)  GET_INT16((p)->p_head.ph_Raid)
  184 #define PK_setRaid(p,l) SET_INT16((p)->p_head.ph_Raid,l)
  185 
  186 /*
  187  *  PROTOCOL INTERPRETER
  188  */
  189 /*
  190 #define NSOCK   256
  191 */
  192 #define NSOCK   64
  193 #define MAXPENDING  4
  194 #define MAXBUFSIZE  ((MAXPENDING+2)*PWSIZE)
  195 typedef struct {
  196     int b_fd;   /* socket file descriptor */
  197     int b_rem;  /* remaining in buffer */
  198     MStr(   b_buf,MAXBUFSIZE);
  199 } Buffer;
  200 
  201 typedef struct {
  202   unsigned int  s_gotHELLO;
  203   unsigned int  s_rrecvN; /* received from remote agent */
  204   unsigned int  s_rrecv;  /* bytes received */
  205   unsigned int  s_rsentN; /* sent to remote agent */
  206   unsigned int  s_rsent;  /* bytes sent */
  207   unsigned int  s_rpendN; /* pending status caused */
  208   unsigned int  s_time; /* the clock of the last activity */
  209   unsigned int  s_wtime; /* the clock of the last write */
  210   unsigned int  s_rtime; /* the clock of the last read */
  211   unsigned int  s_ltCLOSED; /* the clock of closed from local agent */
  212   unsigned int  s_rtCLOSED; /* the clock of closed from remote agent */
  213 } Stats;
  214 
  215 #define AUTH_REQ    1
  216 #define AUTH_OK     2
  217 #define AUTH_ERR    4
  218 
  219 typedef unsigned char Aid;
  220 typedef struct SoxAgent {
  221     int a_abid; /* agent buffer id */
  222     Aid a_Laid; /* local agent id */
  223     Aid a_Xaid; /* remote agent id */
  224   unsigned int  a_rpend; /* bytes pending in remote */
  225   unsigned int  a_stat; /* local agent status */
  226     char    a_remote; /* initiated by remote */
  227     Buffer  a_lbuf; /* buffer for output to local socket */
  228     int a_pid;  /* process id */
  229     Stats   a_stats;
  230     short   a_commin; /* Laid of commin */
  231     short   a_commout; /* Laid of commout */
  232     short   a_Ludp; /* local port is UDP */
  233     short   a_errs; /* error counter */
  234     double  a_start;
  235     int a_authstat;
  236     const char *a_serverurl; /* the local server for this Agent */
  237 } Agent;
  238 
  239 #define a_gotH  a_stats.s_gotHELLO
  240 #define a_recv  a_stats.s_rrecv
  241 #define a_recvN a_stats.s_rrecvN
  242 #define a_sent  a_stats.s_rsent
  243 #define a_sentN a_stats.s_rsentN
  244 #define a_pendN a_stats.s_rpendN
  245 #define a_sock  a_lbuf.b_fd
  246 #define a_lpend a_lbuf.b_rem
  247 #define a_ltCLOSED a_stats.s_ltCLOSED
  248 #define a_rtCLOSED a_stats.s_rtCLOSED
  249 
  250 typedef struct DGSox {
  251     int s_time;
  252     int s_clock;
  253     int s_nlaid;
  254     Credhy  s_credhy[2]; /**/
  255     int s_Rpstats[256]; /* per received packet type */
  256 
  257     MStr(   s_serverurl,256);
  258     MStr(   s_myname,256);
  259     MStr(   s_lhello,64);
  260     MStr(   s_xhello,64);
  261     MStr(   s_Infifo,256);
  262     MStr(   s_Outfifo,256);
  263     MStr(   s_proc,256);
  264     FILE   *s_comminfp;
  265     int s_ocommin;
  266 
  267     int s_agentserno;
  268     int s_agents;
  269     Agent   s_agentbv[NSOCK]; /**/
  270     Agent  *s_agentpv[NSOCK]; /**/
  271     MStr(   s_aidactive,NSOCK);
  272 
  273     int s_qfdset;
  274     int s_qtimeout;
  275     int s_qfdc;
  276     int s_qfdv[NSOCK];
  277     int s_qcxv[NSOCK];
  278     int s_qqev[NSOCK];
  279     int s_commout;
  280     int s_relayOOB;
  281     int s_oneTime;
  282     int s_conndata;
  283     DGC *s_ctx;
  284     MStr(   s_stime,128);
  285 
  286     const char *s_soxinports;
  287 } Sox;
  288 static const char *s_rsap;
  289 static int s_rsap_allow = 0;
  290 
  291 #define ToKey   (&sox->s_credhy[1])
  292 #define TiKey   (&sox->s_credhy[0])
  293 #define Tocrypt ToKey->k_active
  294 #define Ticrypt TiKey->k_active
  295 #define ToCRC8  ToKey->k_crc8
  296 #define TiCRC8  TiKey->k_crc8
  297 
  298 #define Serverurl   sox->s_serverurl
  299 /**/
  300 #define Myname  sox->s_myname
  301 #define LHello  sox->s_lhello
  302 /**/
  303 #define XHello  sox->s_xhello
  304 #define Infifo  sox->s_Infifo
  305 /**/
  306 #define Outfifo sox->s_Outfifo
  307 /**/
  308 #define Comminfp    sox->s_comminfp
  309 #define Ocommin sox->s_ocommin
  310 
  311 #define AgentSerno  sox->s_agentserno
  312 #define Agents  sox->s_agents
  313 #define Agentbv sox->s_agentbv
  314 #define Agentpv sox->s_agentpv
  315 
  316 #define Qfdset  sox->s_qfdset
  317 #define Qtimeout    sox->s_qtimeout
  318 #define Qfdc    sox->s_qfdc
  319 #define Qfdv    sox->s_qfdv
  320 #define Qcxv    sox->s_qcxv
  321 #define Qqev    sox->s_qqev
  322 
  323 #define CommoutFd   sox->s_commout
  324 #define CommOutAp   Agentpv[0]
  325 #define CommInAp    Agentpv[1]
  326 #define RelayOOB    sox->s_relayOOB
  327 #define oneTime     sox->s_oneTime
  328 #define DO_CONNDATA sox->s_conndata
  329 
  330 #define Trecv   CommInAp->a_recv
  331 #define TrecvN  CommInAp->a_recvN
  332 #define Tsent   CommOutAp->a_sent
  333 #define TsentN  CommOutAp->a_sentN
  334 #define TpendN  CommOutAp->a_pendN
  335 
  336 void send_BIND(Sox *sox,Agent *Apc,Packet *pack,PCStr(ports),Agent *Ap1);
  337 void recv_BOUND(Sox *sox,Packet *pack);
  338 void recv_BIND(Sox *sox,Agent *Apc,Packet *pack);
  339 
  340 static int Llinger = 3; /* wait closing local socket with remaining output */
  341 static int DHKgrp = 2;
  342 static int Nodelay = 0;
  343 static int Nopush = 0;
  344 static int Cork = 0;
  345 void set_nopush(int sock,int onoff);
  346 void set_cork(int sock,int onoff);
  347 static int PackSize = 512; /* the small PWSIZE of original version */
  348 static int PackSizeExp = 0;
  349 static int PqueSize = MAXPENDING;
  350 static int sox_private; /* private SockMux of the parent DeleGate */
  351 int iamPrivateSox(){
  352     return sox_private;
  353 }
  354 
  355 /* OPT_S */
  356 #define newAgent        SOX_newAgent
  357 Agent *newAgent(Sox *sox,int raid,int sock,int stat);
  358 #define get_CONNECT     SOX_get_CONNECT
  359 void get_CONNECT(Packet *pack,PVStr(remote),PVStr(local));
  360 #define checkServerFinish   SOX_checkServerFinish
  361 void checkServerFinish(const char *fmt,...);
  362 #define writecomm       SOX_writecomm
  363 int writecomm(Sox *sox,Agent *Apc,Packet *pack);
  364 #define send_ACK        SOX_send_ACK
  365 void send_ACK(Sox *sox,Agent *Apc,Packet *pack);
  366 #define dbgprintf       PK_dbgprintf
  367 int dbgprintf(PCStr(fmt),...);
  368 static int (*dbglog)(PCStr(fmt),...) = dbgprintf;
  369 #define Trace   (*dbglog)
  370 #define Debug   (dbglev==0)?0:(*dbglog)
  371 
  372 #define PK_clrRaid(pack)    PK_setRaid(pack,(Aid)-1)
  373 #define PK_clrSaid(pack)    PK_setSaid(pack,(Aid)-1)
  374 
  375 #ifndef OPT_S /*{*/
  376 
  377 int SOXMUX_UDP_TIMEOUT = 180;
  378 int SOXMUX_UDP_MAX = 64;
  379 int SOX_NOENCRYPT = 0;
  380 int SOX_NOCONNDATA = 0;
  381 
  382 void scan_SOXCONF(DGC*ctx,PCStr(conf))
  383 {   CStr(what,32);
  384     CStr(value,64);
  385 
  386     fieldScan(conf,what,value);
  387     if( streq(what,"dhkey") ){
  388         if( '0' <= *value && *value <= '9' )
  389             DHKgrp = atoi(value);
  390         else    DHKgrp = -1;
  391     }
  392     else
  393     if( streq(what,"noconndata") ){
  394         SOX_NOCONNDATA = 1;
  395     }
  396     else
  397     if( streq(what,"nodelay") ){
  398         if( streq(value,"on") )
  399             Nodelay = 1;
  400     }
  401     else
  402     if( streq(what,"nopush") ){
  403         if( streq(value,"on") )
  404             Nopush = 1;
  405     }
  406     else
  407     if( streq(what,"cork") ){
  408         if( streq(value,"on") )
  409             Cork = 1;
  410     }
  411     else
  412     if( streq(what,"crypt") ){
  413         if( streq(value,"no") || streq(value,"off") )
  414             SOX_NOENCRYPT = 1;
  415     }
  416     else
  417     if( streq(what,"packsize") ){
  418         int size = kmxatoi(value);
  419         if( PWSIZE < size ){
  420             PackSizeExp = PWSIZE;
  421         }else
  422         if( size < 128 ){
  423             PackSizeExp = 128;
  424         }else{
  425             PackSizeExp = size;
  426         }
  427         sv1log("---- PackSizeExp = %d\n",PackSizeExp);
  428     }
  429     else
  430     if( streq(what,"allow") ){
  431         if( isinList(value,"acc") )
  432             s_rsap_allow = 1;
  433     }
  434     else
  435     if( streq(what,"acc") ){
  436         /* SOXCONF="acc:tcp:rhost:rport:lhost:lport" for
  437          *   PORT="rhost:rport" at remote and
  438          *   SERVER="tcprelay://lhost:lport,-in:-:-P{rhost:rport}"
  439          */
  440         sv1log("#### SOXCONF=%s:%s\n",what,value);
  441         s_rsap = stralloc(value);
  442     }
  443     else
  444     if( streq(what,"private") ){
  445         sox_private = 1;
  446     }
  447 }
  448 
  449 static const char *tstmp(Sox *sox){
  450     StrftimeLocal(AVStr(sox->s_stime),sizeof(sox->s_stime),
  451         "%y%m%d-%H%M%S",time(0),0);
  452     return sox->s_stime;
  453 }
  454 
  455 static int sox_init_done = 0;
  456 static int dbglev = 0;
  457 static FILE *logfp;
  458 int dbgprintf(PCStr(fmt),...)
  459 {   CStr(xfmt,256);
  460     int sec,usec;
  461     IStr(msg,2*1024);
  462     VARGS(16,fmt);
  463 
  464     if( lSILENT() && sox_init_done ){
  465         return 0;
  466     }
  467     if( logfp == NULL ){
  468         if( 0 < curLogFd() )
  469             logfp = fdopen(curLogFd(),"a");
  470         else    logfp = stderr;
  471     }
  472     sec = Gettimeofday(&usec);
  473     /*
  474     sprintf(xfmt,"{S}%02d.%03d ",sec%60,usec/1000);
  475     */
  476     sprintf(xfmt,"{S}%02d:%02d.%03d ",(sec%3600)/60,sec%60,usec/1000);
  477     strcat(xfmt,fmt);
  478     strcat(xfmt,"\n");
  479     /*
  480     fprintf(logfp,xfmt,VA16);
  481     */
  482     sprintf(msg,xfmt,VA16);
  483     fprintf(logfp,"%s",msg);
  484     fflush(logfp);
  485 
  486     if( logfp == stderr ){
  487         void send_syslogY(PCStr(lclass),PCStr(log));
  488         if( isWindowsCE() ){
  489             sprintf(msg,xfmt,VA16);
  490             send_syslogY("E",msg);
  491         }
  492     }
  493     return 0;
  494 }
  495 
  496 static int nsigPIPE;
  497 static void sigPIPE(int sig)
  498 {
  499     nsigPIPE++;
  500     signal(SIGPIPE,sigPIPE);
  501 }
  502 static void sigCONT(int sig)
  503 {
  504     signal(SIGCONT,sigCONT);
  505 }
  506 
  507 static int writeb(Sox *sox,Agent *Ap1,char buf[],int len)
  508 {   int wcc,rem;
  509     int wccs;
  510     Buffer *Buf = &Ap1->a_lbuf;
  511 
  512     wcc = 0;
  513     if( Buf->b_rem ){
  514         wcc = write(Buf->b_fd,Buf->b_buf,Buf->b_rem);
  515         Debug("## FLUSHED %d/%d (+%d)",wcc,Buf->b_rem,len);
  516         if( wcc < Buf->b_rem ){
  517             if( wcc < 0 )
  518                 wcc = 0;
  519             rem = Buf->b_rem;
  520             if( 0 < wcc ){
  521                 rem = rem - wcc;
  522                 bcopy(Buf->b_buf+wcc,Buf->b_buf,rem);
  523             }
  524             bcopy(buf,Buf->b_buf+rem,len);
  525             Buf->b_rem = rem + len;
  526             return wcc;
  527         }
  528         Qfdset = 0;
  529         Buf->b_rem = 0;
  530     }
  531     wccs = wcc;
  532 
  533     if( buf != 0 && len ){
  534         wcc = write(Buf->b_fd,buf,len);
  535         if( wcc < len ){
  536             Debug("## SENDING %d/%d",wcc,len);
  537             Qfdset = 0;
  538             if( wcc < 0 )
  539                 wcc = 0;
  540             rem = len - wcc;
  541             bcopy(buf+wcc,Buf->b_buf,rem);
  542             Buf->b_rem = rem;
  543         }
  544         wccs += wcc;
  545     }
  546     return wccs;
  547 }
  548 
  549 static void dumpPack(PCStr(pack),PCStr(epack),int len)
  550 {   int bi;
  551     const char *bp;
  552 
  553     /*
  554     fprintf(stderr,"ORIG ");
  555     bp = pack;
  556     for( bi = 0; bi < len; bi++ )
  557         fprintf(stderr,"%02X",0xFF&*bp++);
  558     fprintf(stderr,"\n");
  559     */
  560     if( epack ){
  561         fprintf(stderr,"ENCD ");
  562         bp = epack;
  563         for( bi = 0; bi < len; bi++ )
  564             fprintf(stderr,"%02X",0xFF&*bp++);
  565         fprintf(stderr,"\n");
  566     }
  567 }
  568 static void getCryptPreamble(Sox *sox,Agent *Api,Packet *pack)
  569 {   CStr(rand,8);
  570     CStr(buf,8);
  571     CStr(tmp,32);
  572     int plen;
  573     int rcc;
  574 
  575     if( 2 <= PK_Leng(pack) )
  576         plen = pack->p_data[PK_Leng(pack)-1];
  577     else    plen = 0;
  578     Trace("#### Encryption start for incoming comm. [%d](%d)/%d",
  579         TiKey->k_group,plen,PK_Leng(pack));
  580     Ticrypt = CRYPT_CREDHY;
  581     if( 0 < plen && plen <= sizeof(buf) ){
  582         rcc = fread(buf,1,QVSSize(buf,plen),Comminfp);
  583         CredhyDecrypt(TiKey,plen,buf,rand);
  584         strtoHex(rand,plen,AVStr(tmp),sizeof(tmp));
  585         if( 2 < dbglev )
  586             Trace("#### GOT PREAMBLE %s",tmp);
  587     }
  588 }
  589 static void putCryptPreamble(Sox *sox,Agent *Api,Packet *pack,int plen)
  590 {   CStr(rand,8);
  591     CStr(buf,8);
  592     CStr(tmp,32);
  593     int rand32,wcc;
  594 
  595     Trace("#### Encryption start for outgoing comm. [%d](%d)",
  596         ToKey->k_group,plen);
  597     Tocrypt = CRYPT_CREDHY;
  598     if( plen ){
  599         rand32 = DH_rand32() ^ getpid();
  600         rand[0] = rand32 >> 24;
  601         rand[1] = rand32 >> 16;
  602         rand[2] = rand32 >> 8;
  603         rand[3] = rand32 >> 0;
  604         CredhyEncrypt(ToKey,plen,rand,buf);
  605         wcc = writeb(sox,Api,buf,plen);
  606         strtoHex(rand,plen,AVStr(tmp),sizeof(tmp));
  607         if( 2 < dbglev )
  608             Trace("#### PUT PREAMBLE %s",tmp);
  609     }
  610 }
  611 static int sendpackX(Sox *sox,Agent *Api,Agent *Apc,Packet *pack,int len,int OOB)
  612 {   int wcc;
  613     Packet *opack;
  614     Packet epack;
  615 
  616     opack = pack;
  617     if( Tocrypt == CRYPT_CREDHY ){
  618         pack->p_Ver = VERENC|MYVER;
  619         CredhyEncrypt(ToKey,len,(char*)pack,(char*)&epack);
  620         if( 2 < dbglev )
  621             dumpPack((char*)pack,(char*)&epack,len);
  622         pack = &epack;
  623     }
  624 
  625     if( OOB && RelayOOB ){
  626         wcc = sendOOB(Apc->a_sock,(char*)pack,len);
  627     }else   wcc = writeb(sox,Apc,(char*)pack,len);
  628 
  629     Apc->a_stats.s_time = sox->s_time;
  630     Apc->a_stats.s_wtime = sox->s_time;
  631     Tsent += wcc;
  632     TsentN++;
  633 /*
  634 Trace("#### SENT %d/%d %d CRC=%X",Tsent,TsentN,len,ToCRC8);
  635 */
  636     if( 0 < wcc && (opack->p_Type & SOX_ACK) == 0 ){
  637         if( Api ){
  638             Api->a_sent += PK_Leng(opack);
  639             Api->a_sentN++;
  640         }
  641     }
  642     if( 1 < dbglev ){
  643         Agent *ApS = 0;
  644         int ci,laid,raid;
  645         for( ci = 0; ci < Agents; ci++ ){
  646             if( Agentpv[ci]->a_Laid == PK_Said(opack) ){
  647                 ApS = Agentpv[ci];
  648                 break;
  649             }
  650         }
  651         laid = PK_Said(opack)!=0xFFFF?PK_Said(opack):-1;
  652         raid = PK_Raid(opack)!=0xFFFF?PK_Raid(opack):-1;
  653         Trace("sendpack L#%d[%02X] -> R#%d[%02X] %d/%d/%d",
  654             laid,ApS?ApS->a_stat:0,
  655             raid,opack->p_Type,
  656             PK_Leng(opack),ApS?ApS->a_sent:0,ApS?ApS->a_sentN:0
  657         );
  658     }
  659     return wcc;
  660 }
  661 static int writecommX(Sox *sox,Agent *ApL,Agent *Apc,Packet *pack)
  662 {   int wcc;
  663 
  664     pack->p_Ver = MYVER;
  665     wcc = sendpackX(sox,ApL,Apc,pack,PHSIZE+PK_Leng(pack),0);
  666     return wcc;
  667 }
  668 int writecomm(Sox *sox,Agent *Apc,Packet *pack)
  669 {
  670     return writecommX(sox,NULL,Apc,pack);
  671 }
  672 static int writesock(Sox *sox,Agent *ApR,Packet *pack)
  673 {   int wcc;
  674 
  675     if( pack == NULL ) /* just to flush pending */
  676         wcc = writeb(sox,ApR,NULL,0);
  677     else    wcc = writeb(sox,ApR,pack->p_data,PK_Leng(pack));
  678     return wcc;
  679 }
  680 static int recvpack(Sox *sox,Agent *Apc,FILE *infp,Packet *pack,int OOB)
  681 {   int rcc,wcc,leng;
  682 
  683     if( OOB && RelayOOB ){
  684         rcc = recvOOB(fileno(infp),GVStr(pack),PHSIZE);
  685     }else   rcc = fread(pack,1,PHSIZE,infp);
  686     if( rcc <= 0 ){
  687         return -1;
  688     }
  689     if( Ticrypt == CRYPT_CREDHY ){
  690         CredhyDecrypt(TiKey,rcc,(char*)pack,(char*)pack);
  691         if( pack->p_Ver != (VERENC|MYVER) ){
  692             Trace("BAD VERSION! %02X %02X|%02X",pack->p_Ver,
  693                 VERENC,MYVER);
  694             return -1;
  695         }
  696     }
  697 
  698     if( 0 < (leng = PK_Leng(pack)) )
  699     {
  700         if( PWSIZE < leng ){
  701             Trace("Too large packet: %d",leng);
  702             return -1;
  703         }
  704         if( OOB && RelayOOB )
  705             rcc += recvOOB(fileno(infp),AVStr(pack->p_data),leng);
  706         else    rcc += fread(pack->p_data,1,QVSSize(pack->p_data,leng),infp);
  707         if( Ticrypt == CRYPT_CREDHY ){
  708             CredhyDecrypt(TiKey,leng,pack->p_data,pack->p_data);
  709         }
  710     }
  711     Apc->a_stats.s_time = sox->s_time;
  712     Apc->a_stats.s_rtime = sox->s_time;
  713     Trecv += rcc;
  714     TrecvN++;
  715 
  716 /*
  717 Trace("#### RECV %d/%d %d CRC=%X",Trecv,TrecvN,rcc,TiCRC8);
  718 */
  719     /*
  720     Debug(" comm input...pack(#%d %02X %d) %d",
  721         PK_Raid(pack),pack->p_Type,PK_Leng(pack),rcc);
  722     */
  723     return rcc;
  724 }
  725 static int sock2comm(Sox *sox,Agent *Api,int sock,Agent *Apc,Packet *pack,int OOB)
  726 {   int laid = Api->a_Laid;
  727     int raid = Api->a_Xaid;
  728     int rcc,wcc,type;
  729     int nrcc;
  730     char buf[8];
  731 
  732     errno = 0;
  733     if( OOB == 2 ){
  734         rcc = PK_Leng(pack);
  735         type = SOX_SENDOOB;
  736 
  737         /* MSG_PEEK clears "exceptfds" in select() */
  738         Trace("----flush OOB %d, withOOB=%d",rcc,withOOB(sock));
  739         nrcc = recv(sock,buf,sizeof(buf),MSG_PEEK);
  740         Trace("----flush OOB %d, withOOB=%d, next non-OOB=%d",
  741             rcc,withOOB(sock),nrcc);
  742     }else
  743     if( OOB ){
  744         rcc = recvOOB(sock,AVStr(pack->p_data),sizeof(pack->p_data));
  745         if( 0 < withOOB(sock) ){
  746             nrcc = recv(sock,buf,sizeof(buf),MSG_PEEK);
  747             Debug("----got OOB %d, withOOB=%d, next non-OOB=%d",
  748                 rcc,withOOB(sock),nrcc);
  749             if( 0 < nrcc && withOOB(sock) ){
  750                 Trace("----pushed OOB %d, non-OOB %d",
  751                     rcc,nrcc);
  752                 PK_setLeng(pack,rcc);
  753                 pack->p_Type = SOX_OOBPUSH;
  754                 return 0;
  755             }
  756         }
  757         else
  758         if( rcc < 0 ){
  759             /* 9.9.0 this might be a local connection and detected
  760              * shutdown() by the peer, to stop farther incoming
  761              * data, as OOB/PRI? (Only with poll(),Ubuntu,SUSE,...)
  762              */
  763             Trace("----sensed OOB but no-OOB and rcc=%d",rcc);
  764             errno = EAGAIN;
  765             return 0;
  766         }
  767         type = SOX_SENDOOB;
  768     }else{
  769         rcc = read(sock,pack->p_data,QVSSize(pack->p_data,PackSize-PHSIZE));
  770         type = SOX_SEND;
  771     }
  772     if( rcc <= 0 ){
  773         Debug("## sock2comm() EOF rcc=%d from client L#%d[%d]",
  774             rcc,laid,sock);
  775         pack->p_Type = SOX_CLOSE;
  776         Api->a_ltCLOSED = sox->s_time;
  777         return rcc;
  778     }
  779     pack->p_Type = type;
  780     PK_setLeng(pack,rcc);
  781     PK_setSaid(pack,laid);
  782     PK_setRaid(pack,raid);
  783 
  784     wcc = sendpackX(sox,Api,Apc,pack,PHSIZE+rcc,OOB);
  785     if( wcc <= 0 ){
  786         Trace("## sock2comm() write %d/%d",wcc,PHSIZE+rcc);
  787     }
  788     /*
  789     Debug(" sock input...pack(#%d %02X %d) %d",
  790         PK_Raid(pack),pack->p_Type,PK_Leng(pack),wcc);
  791     */
  792     return wcc;
  793 }
  794 
  795 static void set_STR(Packet *pack,PCStr(str))
  796 {
  797     FStrncpy(pack->p_data,str);
  798     PK_setLeng(pack,strlen(pack->p_data)+1);
  799 }
  800 static void set_INT(Packet *pack,int ival)
  801 {
  802     sprintf(pack->p_data,"%d",ival);
  803     PK_setLeng(pack,strlen(pack->p_data)+1);
  804 }
  805 static int get_INT(Packet *pack)
  806 {   int ival;
  807 
  808     sscanf(pack->p_data,"%d",&ival);
  809     return ival;
  810 }
  811 
  812 static int SOX_WAITINIT = 1; /* wait the initial data ready (in milli-sec.) */
  813 /*
  814  * initial data which is ready at the begining of a connection is sent
  815  * with a CONNECT request or a CONNECTED response packet
  816  */
  817 static void get_conndata(Sox *sox,Agent *Apn,Packet *pack){
  818     int len;
  819     int pcc;
  820 
  821     if( SOX_NOCONNDATA ) /* it is disabled locally */
  822         return;
  823     if( !DO_CONNDATA ) /* the peer does not ask it */
  824         return;
  825 
  826     if( 0 < PollIn(Apn->a_sock,SOX_WAITINIT) ){
  827         len = strlen(pack->p_data);
  828         /*
  829         pcc = recv(Apn->a_sock,pack->p_data+len+1,PWSIZE-len-1,0);
  830         */
  831         pcc = recv(Apn->a_sock,pack->p_data+len+1,sizeof(pack->p_data)-len-1,0);
  832         if( 0 < pcc ){
  833             PK_setLeng(pack,len+1+pcc);
  834             Trace("CONNECT+DATA send %d (%d)",pcc,PK_Leng(pack));
  835         }
  836     }
  837 }
  838 static void put_conndata(Packet *pack,int clsock)
  839 {   int wcc;
  840     int pcc = 0;
  841     int len;
  842     const char *peek;
  843 
  844     len = strlen(pack->p_data);
  845     if( len+1 < PK_Leng(pack) ){
  846         pcc = PK_Leng(pack) - len - 1;
  847         peek = pack->p_data+len+1;
  848     }
  849     if( pcc <= 0 )
  850         return;
  851 
  852     wcc = send(clsock,peek,pcc,0);
  853     Trace("CONNECT+DATA recv %d / %d (%d)",pcc,wcc,PK_Leng(pack));
  854     if( wcc != pcc ){
  855         /* this is assumed to succeed immediately */
  856         daemonlog("F","SOX CONNECT+DATA failed %d/%d\n",pcc,wcc);
  857     }
  858 }
  859 /*
  860  * CONNECT N.bufsize A.client A.clientif
  861  */
  862 static void set_CONNECT(Agent *Apn,Packet *pack,PCStr(remote),PCStr(local))
  863 {   CStr(pair,512);
  864 
  865     sprintf(pair,"%d %s %s",MAXBUFSIZE,remote,local);
  866     linescanX(pair,AVStr(pack->p_data),sizeof(pack->p_data));
  867     PK_setLeng(pack,strlen(pack->p_data)+1);
  868 }
  869 void get_CONNECT(Packet *pack,PVStr(remote),PVStr(local))
  870 {   int bsiz;
  871 
  872     bsiz = 0;
  873     setVStrEnd(local,0);
  874     setVStrEnd(remote,0);
  875     Xsscanf(pack->p_data,"%d %s %s",&bsiz,AVStr(remote),AVStr(local));
  876 }
  877 
  878 static int send_HELLO(Sox *sox,Agent *Apc,int ack,Packet *pack)
  879 {   int wcc;
  880 
  881     pack->p_Ver = MYVER;
  882     pack->p_Type = ack?SOX_HELLOOK:SOX_HELLO;
  883 
  884     set_STR(pack,LHello);
  885     wcc = sendpackX(sox,NULL,Apc,pack,PHSIZE+PK_Leng(pack),0);
  886     return wcc;
  887 }
  888 static void got_HELLO(Sox *sox,Agent *Api,Packet *pack)
  889 {   const char *data = pack->p_data;
  890     int leng = PK_Leng(pack);
  891 
  892     if( Api->a_gotH != 0 ){
  893         Trace("Got HELLO OK (dup)");
  894         return;
  895     }
  896     if( sizeof(XHello) <= leng )
  897         leng = sizeof(XHello)-1;
  898     XStrncpy(AVStr(XHello),data,leng+1);
  899     Trace("Got HELLO OK[%s]",XHello);
  900     Api->a_gotH = 1;
  901 }
  902 
  903 static void send_doCONNDATA(Sox *sox,Agent *Apc,Packet *pack){
  904     pack->p_Ver = MYVER;
  905     pack->p_Type = SOX_SETOPT;
  906     PK_clrRaid(pack);
  907     PK_clrSaid(pack);
  908     pack->p_data[0] = SOX_O_CONNDATA;
  909     pack->p_data[1] = 1;
  910     pack->p_data[2] = 0;
  911     PK_setLeng(pack,3);
  912     writecomm(sox,Apc,pack);
  913 }
  914 static void send_PACKSIZE(Sox *sox,Agent *Apc,Packet *pack){
  915     int pwsize;
  916 
  917     if( PackSizeExp )
  918         pwsize = PackSizeExp;
  919     else    pwsize = PWSIZE;
  920     pack->p_Ver = MYVER;
  921     pack->p_Type = SOX_SETOPT;
  922     PK_clrRaid(pack);
  923     PK_clrSaid(pack);
  924     pack->p_data[0] = SOX_O_PACKSIZE;
  925     pack->p_data[1] = pwsize >> 8;
  926     pack->p_data[2] = pwsize;
  927     PK_setLeng(pack,3);
  928     writecomm(sox,Apc,pack);
  929     Trace("---- sent my PackSize = %d (max. %d)",pwsize,PWSIZE);
  930 }
  931 static void set_PACKSIZE(Sox *sox,Agent *Api,Packet *pack){
  932     int pwsize;
  933 
  934     pwsize = ((0xFF&pack->p_data[1])<<8) | (0xFF & pack->p_data[2]);
  935     Trace("---- got remote PackSize = %d",pwsize);
  936     if( PackSizeExp ){
  937         if( PackSizeExp < pwsize ){
  938             pwsize = PackSizeExp;
  939         }
  940     }
  941     if( pwsize < PackSize ){
  942         if( 128 < pwsize )
  943             PackSize = pwsize;
  944     }else
  945     if( PackSize < pwsize ){
  946         if( PWSIZE < pwsize )
  947             PackSize = PWSIZE;
  948         else    PackSize = pwsize;
  949     }
  950     Trace("---- set PackSize = %d",PackSize);
  951 }
  952 
  953 static void send_PASS(Sox *sox,Agent *Api,Packet *pack){
  954     DGC*ctx = sox->s_ctx;
  955     CStr(local,128);
  956     CStr(remote,128);
  957     CStr(authb,256);
  958     CStr(host,128);
  959     int port;
  960 
  961     getpairName(Api->a_sock,AVStr(local),AVStr(remote));
  962     Xsscanf(remote,"%[^:]:%d",AVStr(host),&port);
  963     if( get_MYAUTH(ctx,AVStr(authb),"socmux",host,port) ){
  964         pack->p_Type = SOX_SETOPT;
  965         PK_clrRaid(pack);
  966         PK_clrSaid(pack);
  967         pack->p_data[0] = SOX_O_AUTH;
  968         pack->p_data[1] = AUTH_PASS;
  969         Xstrcpy(DVStr(pack->p_data,2),authb);
  970         PK_setLeng(pack,2+strlen(pack->p_data+2)+1);
  971         Trace("---- sent PASSWORD from MYAUTH [%s]",authb);
  972         writecomm(sox,CommOutAp,pack);
  973     }
  974 }
  975 static void recv_AUTH(Sox *sox,Agent *Api,Packet *pack){
  976     int len;
  977     DGC*ctx = sox->s_ctx;
  978     const char *authb = &pack->p_data[2];
  979     AuthInfo auth;
  980     CStr(user,128);
  981     CStr(pass,128);
  982 
  983     if( pack->p_data[1] == AUTH_PASS ){
  984         Trace("---- got PASS[%s] %X",authb,CommInAp->a_authstat);
  985         if( CommInAp->a_authstat & AUTH_REQ ){
  986             bzero(&auth,sizeof(auth));
  987             Xsscanf(authb,"%[^:]:%s",AVStr(user),AVStr(pass));
  988             strcpy(auth.i_user,user);
  989             strcpy(auth.i_pass,pass);
  990             if( 0 <= doAuth(ctx,&auth) ){
  991                 CommInAp->a_authstat |= AUTH_OK;
  992             }else{
  993                 CommInAp->a_authstat |= AUTH_ERR;
  994             }
  995         }
  996     }
  997 }
  998 
  999 static void send_willCRYPT(Sox *sox,Agent *Apc,Packet *pack,int grp)
 1000 {   int len,poff,wcc;
 1001 
 1002     poff = 0;
 1003     pack->p_Ver = MYVER;
 1004     pack->p_Type = SOX_SETOPT;
 1005     PK_clrRaid(pack);
 1006     PK_clrSaid(pack);
 1007     pack->p_data[poff++] = SOX_O_CRYPT;
 1008     pack->p_data[poff++] = CRYPT_CREDHY; /* crypting by XOR CRC8 */
 1009     if( grp == 0 ){
 1010     pack->p_data[poff++] = CRYPT_DHKEY; /* DH key follows */
 1011     }else{
 1012     pack->p_data[poff++] = CRYPT_DHKEYX; /* DH key follows */
 1013     pack->p_data[poff++] = grp; /* DH group */
 1014     }
 1015 
 1016     len = CredhyGenerateKey(ToKey,QVStr(&pack->p_data[poff],pack->p_data),PBSIZE-poff);
 1017     pack->p_data[poff+len+1] = 4; /* desired length of preamble */
 1018     PK_setLeng(pack,poff+len+2);
 1019     wcc = writecomm(sox,Apc,pack);
 1020 }
 1021 static void set_CRYPT(Sox *sox,Agent *Apc,Packet *pack)
 1022 {   int wcc;
 1023     CStr(tmp,512);
 1024     int poff,grp;
 1025     int cv0,plen;
 1026     int elen;
 1027     CStr(ekey,64);
 1028     Packet ipack;
 1029 
 1030     if( TiKey->k_group < 0 ){
 1031         Trace("#Ignore cryption request");
 1032         return;
 1033     }
 1034     poff = 0;
 1035     if( pack->p_data[++poff] != CRYPT_CREDHY ){
 1036         Trace("#Unknown cryption type <%x>",pack->p_data[poff]);
 1037         return;
 1038     }
 1039     cv0 = 0;
 1040     if( pack->p_data[++poff] != CRYPT_DHKEYX ){
 1041         if( pack->p_data[poff] == CRYPT_DHKEY ){
 1042             grp = 0;
 1043             cv0 = 1;
 1044             goto DOWNGRADE;
 1045         }else{
 1046         Trace("#No cryption key given <%x>",pack->p_data[poff]);
 1047         return;
 1048         }
 1049     }
 1050     grp = pack->p_data[++poff];
 1051     if( grp != ToKey->k_group ){
 1052 DOWNGRADE:
 1053         if( ToKey->k_group < grp ){
 1054         Trace("##Unmatch group R=%d L=%d",grp,ToKey->k_group);
 1055         return;
 1056         }
 1057         if( grp < ToKey->k_group ){
 1058         Packet rpack;
 1059         Trace("##Downgrade key from #%d to #%d",ToKey->k_group,grp);
 1060         CredhyInit(ToKey,grp);
 1061         CredhyInit(TiKey,grp);
 1062         rpack = *pack;
 1063         send_willCRYPT(sox,Apc,&rpack,grp);
 1064         }
 1065     }
 1066 
 1067     ++poff;
 1068     strtoHex(&pack->p_data[poff],PK_Leng(pack)-poff,AVStr(tmp),sizeof(tmp));
 1069     Debug("got CRYPT[%s]",tmp);
 1070     if( CredhyAgreedKey(ToKey,&pack->p_data[poff]) != 0 ){
 1071         Trace("#Bad cryption key given");
 1072         sleep(10);
 1073         return;
 1074     }
 1075     ipack = *pack;
 1076     if( 0 < (elen = getCKey(AVStr(ekey),sizeof(ekey))) ){
 1077         CredhyEncrypt(ToKey,elen,ekey,ekey);
 1078         bzero(ekey,elen);
 1079     }
 1080     *TiKey = *ToKey;
 1081     /* generate up/down asymmetry */
 1082     TiCRC8 = strCRC8(TiCRC8,TiKey->k_rcrc8,1);
 1083     ToCRC8 = strCRC8(ToCRC8,ToKey->k_lcrc8,1);
 1084 
 1085     pack->p_Type = SOX_CRYPTON;
 1086     pack->p_data[0] = CRYPT_CREDHY;
 1087 
 1088     if( fileno(Comminfp) != CommoutFd ){
 1089         Trace("Don't put preamble on separate comm[%d %d]",
 1090             fileno(Comminfp),CommoutFd);
 1091         plen = 0;
 1092         PK_setLeng(pack,1);
 1093     }else
 1094     if( !cv0 && (plen = pack->p_data[PK_Leng(pack)-1]) ){
 1095         pack->p_data[1] = plen; /* preamble length to be sent */
 1096         PK_setLeng(pack,2);
 1097     }else{
 1098         plen = 0;
 1099         PK_setLeng(pack,1);
 1100     }
 1101     wcc = writecomm(sox,Apc,pack);
 1102     putCryptPreamble(sox,Apc,&ipack,plen);
 1103 
 1104     if( file_issock(sox->s_commout) < 0 ){
 1105         sv1log("#### NotSocket[%d] WAIT for what?\n",sox->s_commout);
 1106         /* bug: decryption may fail at the receiver end ... */
 1107         msleep(100);
 1108     }
 1109 }
 1110 
 1111 static int send_PING(Sox *sox,Agent *Apc,Packet *pack)
 1112 {   int wcc;
 1113     CStr(stime,64);
 1114     int sec,usec,msec;
 1115 
 1116     pack->p_Type = SOX_ECHO;
 1117     PK_clrRaid(pack);
 1118     PK_clrSaid(pack);
 1119     sec = Gettimeofday(&usec);
 1120     msec = sec*1000 + usec/1000;
 1121     set_INT(pack,msec);
 1122     wcc = writecomm(sox,Apc,pack);
 1123 
 1124     getTimestamp(AVStr(stime));
 1125     Debug("Put ECHO [%u] %s #%d (%d)",msec,stime,TsentN,wcc);
 1126     return wcc;
 1127 }
 1128 static int commInactive(Sox *sox)
 1129 {   int ci;
 1130     Agent *Ap1;
 1131     int rtime,wtime,noresp;
 1132 
 1133     rtime = wtime = 0;
 1134     for( ci = 0; ci < Agents; ci++ ){
 1135         Ap1 = Agentpv[ci];
 1136         if( Ap1->a_stat == SOX_COMMOUT ){
 1137             wtime = Ap1->a_stats.s_wtime;
 1138         }else
 1139         if( Ap1->a_stat == SOX_COMMIN ){
 1140             rtime = Ap1->a_stats.s_rtime;
 1141         }
 1142     }
 1143     if( rtime == 0 || wtime == 0 )
 1144         return 0;
 1145 
 1146     noresp = wtime - rtime;
 1147     return noresp;
 1148 }
 1149 void send_ACK(Sox *sox,Agent *Apc,Packet *pack)
 1150 {   int tid;
 1151 
 1152     pack->p_Type |= SOX_ACK;
 1153     tid  = PK_Said(pack);
 1154     PK_setSaid(pack,PK_Raid(pack));
 1155     PK_setRaid(pack,tid);
 1156     writecomm(sox,Apc,pack);
 1157 }
 1158 
 1159 static int newlaid(Sox *sox)
 1160 {   int ci;
 1161 
 1162     for( ci = sox->s_nlaid; ci < NSOCK-1; ci++ )
 1163         if( sox->s_aidactive[ci] == 0 )
 1164             goto EXIT;
 1165 
 1166     for( ci = 0; ci < sox->s_nlaid; ci++ )
 1167         if( sox->s_aidactive[ci] == 0 )
 1168             goto EXIT;
 1169 
 1170     return -1;
 1171 EXIT:
 1172     sox->s_aidactive[ci] = 1;
 1173     sox->s_nlaid = ci + 1;
 1174     return ci;
 1175 }
 1176 
 1177 static void sweepAgents(Sox *sox)
 1178 {   int ai,idle,nudp,maxi,maxit;
 1179     Agent *Ap,*Api;
 1180 
 1181     nudp = 0;
 1182     Api = 0;
 1183     maxit = -1;
 1184     for( ai = 0; ai < Agents; ai++ ){
 1185         Ap = Agentpv[ai];
 1186         if( !Ap->a_Ludp )
 1187             continue;
 1188 
 1189         nudp++;
 1190         idle = sox->s_time - Ap->a_stats.s_time;
 1191         if( maxit < idle ){
 1192             Api = Ap;
 1193             maxit = idle;
 1194         }
 1195         if( idle < SOXMUX_UDP_TIMEOUT )
 1196             continue;
 1197 
 1198         Ap->a_stat = SOX_CLOSED;
 1199         Trace("Timeout L#%d[%d]%d idle=%ds",
 1200             Ap->a_Laid,Ap->a_abid,Ap->a_sock,
 1201             idle);
 1202     }
 1203     if( SOXMUX_UDP_MAX < nudp ){
 1204         if( Api->a_stat != SOX_CLOSED ){
 1205             Trace("Pushout L#%d[%d]%d idle=%ds",
 1206                 Api->a_Laid,Api->a_abid,Api->a_sock,
 1207                 sox->s_time - Api->a_stats.s_time);
 1208             Api->a_stat = SOX_CLOSED;
 1209         }
 1210     }
 1211 }
 1212 Agent *newAgent(Sox *sox,int raid,int sock,int stat)
 1213 {   Agent *Apn;
 1214     int bid;
 1215 
 1216     sweepAgents(sox);
 1217 
 1218     if( elnumof(Agentpv) <= Agents ){
 1219         static Agent dummy;
 1220         syslog_ERROR("#### FATAL: Too many agents ####\n");
 1221         return &dummy;
 1222     }
 1223 
 1224     AgentSerno++;
 1225     Apn = Agentpv[Agents++];
 1226     bid = Apn->a_abid;
 1227     bzero(Apn,sizeof(Agent));
 1228     Apn->a_abid = bid;
 1229 
 1230     Apn->a_Laid = newlaid(sox);
 1231     Apn->a_Xaid = raid;
 1232     Apn->a_sock = sock;
 1233     Apn->a_stat = stat;
 1234     Apn->a_start = Time();
 1235     return Apn;
 1236 }
 1237 static void delAgent(Sox *sox,int ci)
 1238 {   int cj;
 1239     Agent *Ap1;
 1240 
 1241     if( ci != Agents-1 ){
 1242         Ap1 = Agentpv[ci];
 1243         for( cj = ci; cj < Agents-1; cj++ ){
 1244             Agentpv[cj] = Agentpv[cj+1];
 1245         }
 1246         Agentpv[Agents-1] = Ap1;
 1247     }
 1248     Agents--;
 1249 }
 1250 static void dumpAgent(PCStr(what),Agent *Ap1)
 1251 {   CStr(local,256);
 1252     CStr(remote,256);
 1253 
 1254     getpairName(Ap1->a_sock,AVStr(local),AVStr(remote));
 1255     if( strncmp(local,"0.0.0.0:",8) == 0 )
 1256         Strrplc(AVStr(local),7,"*");
 1257     Trace("%s[%2d] L#%d[%02X] R#%d P=%d,%d S=%d/%d R=%d/%d [%s %s]",
 1258         what,
 1259         Ap1->a_sock,Ap1->a_Laid,Ap1->a_stat,Ap1->a_Xaid,
 1260         Ap1->a_pendN,Ap1->a_lbuf.b_rem,
 1261         Ap1->a_sent,Ap1->a_sentN,
 1262         Ap1->a_recv,Ap1->a_recvN,
 1263         local,remote);
 1264 }
 1265 static int Nshut;
 1266 void sox_dumpFds(Sox *sox,PVStr(fds),int siz);
 1267 static void shutdownAgents(Sox *sox)
 1268 {   int ci;
 1269     Agent *Ap1;
 1270     CStr(fds,256);
 1271 
 1272     sox_dumpFds(sox,AVStr(fds),sizeof(fds));
 1273     Trace("SHUTDOWN#%d (%d){%s}",++Nshut,Qfdc,fds);
 1274     for( ci = 0; ci < Agents; ci++ ){
 1275         Ap1 = Agentpv[ci];
 1276         dumpAgent("shut",Ap1);
 1277     }
 1278     for( ci = 0; ci < Agents; ci++ ){
 1279         Ap1 = Agentpv[ci];
 1280         if( Ap1->a_stat != SOX_LISTEN )
 1281         {
 1282             if( Ap1->a_stat == SOX_PARENT ){
 1283                 Trace("## DONT close parent[%d]",Ap1->a_sock);
 1284             }else
 1285             close(Ap1->a_sock);
 1286             Ap1->a_sock = -1;
 1287             Ap1->a_stat = SOX_CLOSED;
 1288         }
 1289     }
 1290     if( CTX_withYY(sox->s_ctx) ){
 1291         finishServYY(FL_ARG,sox->s_ctx);
 1292         finishClntYY(FL_ARG,sox->s_ctx);
 1293         sv1log("--yySox shutdown\n");
 1294     }
 1295 }
 1296 
 1297 int sox_connects(void *sc,Sox *sox,DGC*ctx,PVStr(local),PVStr(remote),int itvl);
 1298 #define connects(ctx,lo,re,iv) sox_connects(optctx(ctx),sox,ctx,lo,re,iv)
 1299 
 1300 int CTX_CantResolv(DGC*ctx);
 1301 void clear_DGserv(DGC*ctx);
 1302 
 1303 #include "param.h"
 1304 int SoxOutPort = -1; /* from PrivateSox to the owner DeleGate */
 1305 int SyncHTMUX = -1;
 1306 
 1307 static void sox_init(Sox *sox,DGC*ctx,int ac,const char *av[],int *comminp,int *commoutp,PVStr(server),int ssiz)
 1308 {   int commin,commout;
 1309     int ai;
 1310     int stat;
 1311     CStr(local,256);
 1312     CStr(remote,256);
 1313     CStr(tmp,256);
 1314     int sock;
 1315 
 1316     dbglev = LOGLEVEL;
 1317     commin = *comminp;
 1318     commout = *commoutp;
 1319     for( ai = 0; ai < ac; ai++ ){
 1320         const char *arg; /**/
 1321         const char *pp;
 1322         arg = av[ai];
 1323         if( isPrivateSox(ctx) ){
 1324             sv1log("--Sox[%d] %s\n",ai,arg);
 1325         }
 1326         if( pp = parameq(arg,P_SOXOUTPORT) ){
 1327             SoxOutPort = atoi(pp);
 1328         }else
 1329         if( strncasecmp(arg,"-A",2) == 0 ){
 1330         /* accept commin/commout */
 1331         remote[0] = 0;
 1332         sock = VSocket(ctx,"BIND/SOX*",-1,CVStr(arg+2),AVStr(remote),"listen=1");
 1333         Trace("BIND %d",sock);
 1334 
 1335         ACC_TIMEOUT = 0;
 1336         local[0] = remote[0] = 0;
 1337         commin = commout =
 1338             VSocket(ctx,"ACPT/SOX*",sock,AVStr(local),AVStr(remote),"");
 1339         Trace("ACPT %d",commin);
 1340 
 1341         close(sock);
 1342         }else
 1343         if( strncasecmp(arg,"-C",2) == 0 ){ /* connect commin/commout */
 1344         int citvl = 5;
 1345         const char *hp; /**/
 1346 
 1347         hp = arg+2;
 1348         if( *hp == '-' ){
 1349             hp = numscanX(hp+1,AVStr(tmp),sizeof(tmp));
 1350             citvl = atoi(tmp);
 1351             if( citvl <= 0 )
 1352                 citvl = 1;
 1353             if( *hp == '-' )
 1354                 hp++;
 1355         }
 1356         strcpy(local,"*:*");
 1357         commin = commout = connects(ctx,AVStr(local),CVStr(hp),citvl);
 1358         }else
 1359         if( strncasecmp(arg,"-B",2) == 0 ){
 1360         /* accept() to be issued by remote agent */
 1361         sock = VSocket(ctx,"BIND/SOX*",-1,CVStr(arg+2),AVStr(remote),"listen=8");
 1362         Trace("## BIND for rmote: %d",sock);
 1363         }else
 1364         if( strncasecmp(arg,"-X",2) == 0 ){
 1365         commin = commout = open(arg+2,2);
 1366         Trace("COMM IN/OUT=%d %s",commin,arg+2);
 1367         }else
 1368         if( strncasecmp(arg,"-I",2) == 0 ){
 1369         commin = open(arg+2,2);
 1370         Trace("COMM IN=%d %s",commin,arg+2);
 1371         }else
 1372         if( strncasecmp(arg,"-O",2) == 0 ){
 1373         commout = open(arg+2,2);
 1374         Trace("COMM OUT=%d %s",commout,arg+2);
 1375         }else
 1376         if( strncasecmp(arg,"-Q",2) == 0 ){
 1377         setVStrEnd(server,0);
 1378         if( strstr(arg,"://") == 0 )
 1379             wordscanX("tcprelay://",AVStr(server),ssiz);
 1380         wordscanX(arg+2,TVStr(server),ssiz-strlen(server));
 1381         }else
 1382         if( strncasecmp(arg,"-v",2) == 0 ){
 1383         switch(arg[2]){
 1384             case 'v':
 1385             case 'd':
 1386                 dbglev = 1;
 1387                 break;
 1388         }
 1389         }
 1390     }
 1391     *comminp = commin;
 1392     *commoutp = commout;
 1393 }
 1394 static int getserver(DGC*ctx,PCStr(proto),PVStr(serverurl),PCStr(from),PCStr(rclif),xPVStr(mbox),int msiz)
 1395 {   CStr(mboxb,256);
 1396     const char *dp;
 1397     CStr(addr,256);
 1398     int port;
 1399 
 1400     addr[0] = 0;
 1401     port = 0;
 1402     if( from != NULL ){
 1403         if( dp = wordScanY(from,addr,"^:") )
 1404         if( *dp == ':' )
 1405             port = atoi(dp+1);
 1406     }
 1407     VA_setClientAddr(ctx,addr,port,1);
 1408 
 1409     HL_setClientIF(NULL,0,1);
 1410     if( rclif != NULL ){
 1411         wordscanX(rclif,AVStr(addr),sizeof(addr));
 1412         if( dp = strchr(addr,':') ){
 1413             port = atoi(dp+1);
 1414             truncVStr(dp);
 1415         }else   port = 0;
 1416         HL_setClientIF(addr,port,1);
 1417     }
 1418 
 1419     if( mbox == 0 ){
 1420         setPStr(mbox,mboxb,sizeof(mboxb));
 1421         msiz = sizeof(mboxb);
 1422     }
 1423     setVStrEnd(mbox,0);
 1424     if( from == 0 ){
 1425         wordscanX("-@-",AVStr(mbox),msiz);
 1426     }else{
 1427         if( strchr(from,'@') ){
 1428             wordscanX(from,TVStr(mbox),msiz-strlen(mbox));
 1429         }else{
 1430             wordscanX("-@",TVStr(mbox),msiz-strlen(mbox));
 1431             wordscanX(from,TVStr(mbox),msiz-strlen(mbox));
 1432         }
 1433     }
 1434 
 1435     setClientCert(ctx,"SOX",mbox);
 1436     set_realproto(ctx,proto);
 1437     if( find_CMAP(ctx,"XSERVER",AVStr(serverurl)) < 0 )
 1438     {
 1439         return 0;
 1440     }
 1441     return 1;
 1442 }
 1443 
 1444 /*
 1445  * accept from local socket, then connect at remote host
 1446  */
 1447 static void sox_accept1(Sox *sox,DGC*ctx,Agent *Api,Packet *pack)
 1448 {   CStr(local,256);
 1449     CStr(remote,256);
 1450     Agent *Apn;
 1451     int clsock;
 1452     int aid;
 1453     int wcc;
 1454 
 1455     strcpy(local,"*:*");
 1456     strcpy(remote,"*:*");
 1457     errno = 0;
 1458     clsock = VSocket(ctx,"ACPT/SOX",Api->a_sock,AVStr(local),AVStr(remote),"");
 1459     Trace("L#%d accept(%d)=%d [%s]<-[%s] errno=%d",
 1460         Api->a_Laid,Api->a_sock,clsock,remote,local,errno);
 1461     if( clsock < 0 )
 1462         return;
 1463 
 1464     set_ClientSock(ctx,clsock,remote,local);
 1465     if( isPrivateSox(ctx) ){
 1466     }else
 1467     if( !source_permitted(ctx) ){
 1468         Trace("Forbidden %s",remote);
 1469         close(clsock);
 1470         return;
 1471     }
 1472     if( 0 <= clsock ){
 1473         CTX_setSockBuf(FL_ARG,ctx,clsock,1);
 1474     }
 1475 
 1476     setNonblockingIO(clsock,1);
 1477     set_nodelay(clsock,1);
 1478 
 1479     Apn = newAgent(sox,-1,clsock,SOX_CONNECT);
 1480     Apn->a_Ludp = isUDPsock(clsock);
 1481     aid = Apn->a_Laid;
 1482     Apn->a_remote = 0;
 1483     Qfdset = 0;
 1484 
 1485     pack->p_Type = SOX_CONNECT;
 1486     PK_setSaid(pack,aid);
 1487     PK_clrRaid(pack);
 1488     set_CONNECT(Apn,pack,remote,local);
 1489     get_conndata(sox,Apn,pack);
 1490     Trace("CONN> L#%d[%s]",aid,pack->p_data);
 1491     wcc = writecomm(sox,CommOutAp,pack);
 1492 }
 1493 /*
 1494  * SERVER=proto://host:port or SERVER=proto
 1495  */
 1496 int sox_connect1(void *sc,DGC*ctx,Packet *pack,PCStr(serverURL),PVStr(remote),PVStr(local),int *pidp);
 1497 int sox_connect0(void *sc,DGC*ctx,Packet *pack,PCStr(serverURL),PVStr(remote),PVStr(local),int *pidp)
 1498 {   int clsock,logfd;
 1499     CStr(servU,256);
 1500     CStr(proto,64);
 1501     CStr(serv,256);
 1502     CStr(opt,256);
 1503     CStr(param,256);
 1504     CStr(mbox,256);
 1505     CStr(client,256);
 1506     CStr(clif,256);
 1507     int sockv[2];
 1508     const char *dp;
 1509     const char *ep;
 1510     int pid;
 1511     int ai;
 1512 
 1513     linescanX(serverURL,AVStr(servU),sizeof(servU));
 1514     get_CONNECT(pack,AVStr(client),AVStr(clif));
 1515 
 1516     if( servU[0] && strstr(servU,",-fixin") ){
 1517         sv1log("#### connect[%s][%s] R#%d L#%d\n",
 1518             remote,servU,PK_Said(pack),PK_Raid(pack));
 1519     }else
 1520     getserver(ctx,"vp_in",AVStr(servU),client,clif,AVStr(mbox),sizeof(mbox));
 1521 
 1522     if( servU[0] == 0 ){
 1523         Trace("No server L#%d R#%d %s <- %s",
 1524             PK_Raid(pack),PK_Said(pack),clif,client);
 1525         return -1;
 1526     }
 1527 
 1528     Trace("SERVER=%s",servU);
 1529     param[0] = 0;
 1530     if( dp = strchr(servU,'(') ){
 1531         wordScanY(dp+1,param,"^)");
 1532         if( ep = strchr(servU,')')  )
 1533             ovstrcpy((char*)dp,ep+1);
 1534     }
 1535     opt[0] = 0;
 1536     if( dp = strchr(servU,',') ){
 1537         wordscanX(dp,AVStr(opt),sizeof(opt));
 1538         truncVStr(dp);
 1539     }
 1540     proto[0] = serv[0] = 0;
 1541     Xsscanf(servU,"%[^:]://%[^/?]",AVStr(proto),AVStr(serv));
 1542     if( serv[0] && strchr(serv,':') == 0 )
 1543     if( !streq(serv,"-") && !streq(serv,"-.-") )
 1544     {
 1545         Xsprintf(TVStr(serv),":%d",serviceport(proto));
 1546     }
 1547     if( streq(proto,"udprelay") )
 1548         strcat(serv,".udp");
 1549     Trace("SERVER=%s://%s/%s(%s):-:%s",proto,serv,opt,param,mbox);
 1550 
 1551     if( streq(serv,"-") || streq(serv,"-.-") || param[0] ){
 1552         const char *av[32]; /**/
 1553         CStr(ab,1024);
 1554         refQStr(ap,ab); /**/
 1555         int ac,fd,fd0,fd1,fd2;
 1556 
 1557         /*
 1558         INET_Socketpair(sockv);
 1559         */
 1560         if( INET_Socketpair(sockv) < 0 ){
 1561             Trace("Could not get Socketpair()");
 1562             return -1;
 1563         }
 1564         clsock = sockv[0];
 1565         setserversock(sockv[1]);
 1566         logfd = curLogFd();
 1567         for( fd = 0; fd < NSOCK; fd++ ){
 1568             if( fd != sockv[1] )
 1569             if( fd != logfd )
 1570             if( fd != fileno(stderr) )
 1571                 setCloseOnExec(fd);
 1572         }
 1573         ac = 0;
 1574         ap = ab;
 1575         sprintf(ap,"SERVER=%s://%s",proto,serv);
 1576         av[ac++] = ap; ap += strlen(ap) + 1;
 1577         sprintf(ap,"-P-%s",clif);
 1578         av[ac++] = ap; ap += strlen(ap) + 1;
 1579         sprintf(ap,"-L0x%x/%d",LOG_type,logfd);
 1580         av[ac++] = ap; ap += strlen(ap) + 1;
 1581         sprintf(ap,"ADMIN=%s",getADMIN());
 1582         av[ac++] = ap; ap += strlen(ap) + 1;
 1583 {
 1584 FILE *fopenSvstats(PCStr(serv),PCStr(mode));
 1585 FILE *fopenInitLog(PCStr(name),PCStr(mode));
 1586     static FILE *sfp; 
 1587     static FILE *ifp; 
 1588     CStr(serv,128);
 1589 
 1590     if( sfp == NULL ){
 1591         sprintf(serv,"_sockmux_");
 1592         sfp = fopenSvstats(serv,"w+");
 1593         ifp = fopenInitLog(serv,"a+");
 1594     }
 1595     if( sfp ){
 1596         sprintf(ap,"-IS%d",fileno(sfp));
 1597         av[ac++] = ap; ap += strlen(ap) + 1;
 1598     }
 1599     if( ifp ){
 1600         sprintf(ap,"-II%d",fileno(ifp));
 1601         av[ac++] = ap; ap += strlen(ap) + 1;
 1602     }
 1603  }
 1604 
 1605         /*
 1606         sscanf (pack->p_data,"%s %s",rclient,rhost);
 1607         sprintf(ap,"_remoteport=%s",rsvd);
 1608         av[ac++] = ap; ap += strlen(ap) + 1;
 1609         */
 1610 
 1611         if( param[0] ){
 1612             ac += decomp_args(&av[ac],32-ac,param,AVStr(ap));
 1613         }
 1614         av[ac] = 0;
 1615         for( ai = 0; ai < ac; ai++ ){
 1616             Debug("[%d] %s",ai,av[ai]);
 1617         }
 1618         fd0 = dup(0); fd1 = dup(1); fd2 = dup(2);
 1619         dup2(sockv[1],0);
 1620         dup2(sockv[1],1);
 1621         dup2(fileno(stderr),2);
 1622         pid = spawnv_self1(ac,av);
 1623         close(sockv[1]);
 1624         dup2(fd0,0); dup2(fd1,1); dup2(fd2,2);
 1625         close(fd0); close(fd1); close(fd2);
 1626         Trace("Fork pid=%d",pid);
 1627         NUM_CHILDREN++;
 1628         CHILD_SERNO++;
 1629         putLoadStat(ST_ACC,1);
 1630         put_svstat();
 1631         *pidp = pid;
 1632     }else{
 1633         void initConnect(DGC*ctx);
 1634         initConnect(ctx);
 1635 
 1636         /* this connect should be in non-blocking */
 1637         setVStrEnd(local,0);
 1638         clsock = VSocket(ctx,"CNCT/SOX",-1,AVStr(local),AVStr(serv),"self");
 1639         *pidp = 0;
 1640     }
 1641     if( 0 <= clsock ){
 1642         gethostName(clsock,AVStr(local),"%A:%P");
 1643         getpeerName(clsock,AVStr(remote),"%A:%P");
 1644     }
 1645     return clsock;
 1646 }
 1647 static void getcommpath(PCStr(fifo),PVStr(path))
 1648 {   const char *dp;
 1649 
 1650     setVStrEnd(path,0);
 1651     if( dp = strstr(fifo,"@") )
 1652     {
 1653         strcpy(path,dp+1);
 1654     }
 1655 }
 1656 Sox *sox_setup1(DGC*ctx)
 1657 {   CStr(fifo,256);
 1658     Sox *sox;
 1659     int sec,usec,len;
 1660 
 1661     sox = (Sox*)calloc(1,sizeof(Sox));
 1662 
 1663     if( lVERB() )
 1664     if( dbglev == 0 )
 1665         dbglev = 1;
 1666 
 1667     bzero(sox,sizeof(Sox));
 1668     sox->s_ctx = ctx;
 1669 
 1670     sec = Gettimeofday(&usec);
 1671     StrftimeGMT(AVStr(LHello),sizeof(LHello),"%Y%m%d-%H%M%S%.6s ",sec,usec);
 1672     gethostname(Myname,sizeof(Myname));
 1673     len = strlen(LHello);
 1674     XStrncpy(NVStr(LHello) LHello+len,Myname,sizeof(LHello)-len);
 1675 
 1676     Ocommin = -1;
 1677     Qtimeout = -1; /* infinite wait for PollInsOuts() */
 1678 
 1679     if( getserver(ctx,"vp_comm",AVStr(fifo),NULL,NULL,VStrNULL,0) ){
 1680         getcommpath(fifo,AVStr(Infifo));
 1681         strcpy(Outfifo,Infifo);
 1682         Trace("comm=%s [%s]",Infifo,fifo);
 1683     }
 1684     if( getserver(ctx,"vp_commin",AVStr(fifo),NULL,NULL,VStrNULL,0) ){
 1685         getcommpath(fifo,AVStr(Infifo));
 1686         Trace("commin=%s [%s]",Infifo,fifo);
 1687     }
 1688     if( getserver(ctx,"vp_commout",AVStr(fifo),NULL,NULL,VStrNULL,0) ){
 1689         getcommpath(fifo,AVStr(Outfifo));
 1690         Trace("commout=%s [%s]",Outfifo,fifo);
 1691     }
 1692     if( getserver(ctx,"vp_proc",AVStr(fifo),NULL,NULL,VStrNULL,0) ){
 1693         getcommpath(fifo,AVStr(sox->s_proc));
 1694         Trace("proc=%s",sox->s_proc);
 1695     }
 1696     return sox;
 1697 }
 1698 
 1699 int SoxImmRestart;
 1700 /*
 1701 int sox_setup(int ac,const char *av[],DGC*ctx,int svsock,int svport,Sox *sox)
 1702 */
 1703 int sox_setupX(int ac,const char *av[],DGC*ctx,int svsock,int svport,Sox *sox,int insock,int inport)
 1704 {   const char *isvproto;
 1705     const char *isvhost = 0;
 1706     int isvport = 0;
 1707     int stat;
 1708     int commin;
 1709     int ci;
 1710     int rcode;
 1711     Packet packb,*pack = &packb;
 1712     CStr(local,256);
 1713     CStr(remote,256);
 1714     Agent *Ap1,*Apn,*Apb;
 1715     int wcc,rcc,pid;
 1716     int sockc,portv[NSOCK],sockv[NSOCK];
 1717     int ntry = 0;
 1718 
 1719     if( 1 ){
 1720         int ai;
 1721         const char *a1;
 1722         const char *pp;
 1723         for( ai = 0; ai < ac; ai++ ){
 1724             a1 = av[ai];
 1725             if( pp = parameq(a1,P_SYNCHTMUX) ){
 1726                 SyncHTMUX = atoi(pp);
 1727             }else
 1728             if( pp = parameq(a1,P_SOXINPORTS) ){
 1729                 sox->s_soxinports = pp;
 1730             }
 1731         }
 1732     }
 1733     if( lSINGLEP() && isPrivateSox(ctx) ){
 1734         int ai;
 1735         const char *a1;
 1736         IStr(host,256);
 1737         int port = 8707;
 1738 
 1739         for( ai = 0; ai < ac; ai++ ){
 1740             a1 = av[ai];
 1741             if( strneq(a1,"SERVER=sockmux://",17) ){
 1742                 Xsscanf(a1+17,"%[^:]:%d",AVStr(host),&port);
 1743                 isvproto = "sockmux";
 1744                 isvhost = stralloc(host);
 1745                 isvport = port;
 1746             }else
 1747             if( strneq(a1,"SOXCONF=",8) ){
 1748                 scan_SOXCONF(ctx,a1+8);
 1749             }
 1750         }
 1751         sockv[0] = svsock;
 1752         sockc = 1;
 1753         if( 1 ){
 1754             /* should be by SOXCONF=dhkey:none if necessary */
 1755         }else
 1756         DHKgrp = -1; /* WinCE on ARM ? */
 1757     }else{
 1758     isvport = CTX_get_iserver(ctx,&isvproto,&isvhost);
 1759     sockc = getReservedPorts(portv,sockv);
 1760     }
 1761     if( 0 <= insock ){
 1762         portv[sockc] = inport;
 1763         sockv[sockc] = insock;
 1764         sockc++;
 1765         for( ci = 0; ci < sockc; ci++ ){
 1766             porting_dbg("###SoxIn(%d) PORT[%d/%d]",
 1767                 ci,portv[ci],sockv[ci]);
 1768         }
 1769     }
 1770 
 1771     if( 0 <= DHKgrp ){
 1772         CredhyInit(ToKey,DHKgrp);
 1773         CredhyInit(TiKey,DHKgrp);
 1774     }else{
 1775         ToKey->k_group = -1;
 1776         TiKey->k_group = -1;
 1777     }
 1778 
 1779     if( 0 < svport && IsConnected(svsock,NULL) ){
 1780         commin = CommoutFd = svsock;
 1781         Trace("Given Connected Socket [%d]",svsock);
 1782         oneTime = 1;
 1783         goto CONNDONE;
 1784     }
 1785 
 1786 RETRY:
 1787     if( oneTime )
 1788         return -1;
 1789 
 1790     if( 3 < ntry++ ){
 1791         sleep(3);
 1792     }
 1793 
 1794     CFI_DISABLE = 0;
 1795     close_FSV(ctx);
 1796     if( 0 <= Ocommin ){
 1797         Trace("## Close old commin hidden by FCL: %d",Ocommin);
 1798         close(Ocommin);
 1799         Ocommin = -1;
 1800     }
 1801     if( Comminfp != NULL ){
 1802         Trace("## Close Comminfp %d/%X",fileno(Comminfp),Comminfp);
 1803         fshutdown(Comminfp,1);
 1804         fclose(Comminfp);
 1805         Comminfp = NULL;
 1806 
 1807         Trace("## [%d.%X] %d) %d %d",getpid(),PRTID(getthreadid()),
 1808             ntry,isPrivateSox(ctx),AccViaHTMUX);
 1809         if( lSINGLEP() && isPrivateSox(ctx) ){
 1810             /* maybe this delay is for non-socket/IP Commin */
 1811         }else
 1812         if( SoxImmRestart ){
 1813             SoxImmRestart = 0;
 1814             Trace("## Set Restart Immediately");
 1815         }else
 1816         if( ntry < 3 ){
 1817         }else
 1818         sleep(5);
 1819     }
 1820     /*
 1821     while( 0 < (pid = NoHangWait()) ){
 1822     */
 1823     while( 0 < (pid = timeoutWait(100)) ){
 1824         Trace("Exit pid=%d",pid);
 1825     }
 1826     set_ClientSock(ctx,-1,"","");
 1827 
 1828     commin = CommoutFd = -1;
 1829     if( commin < 0 && sox->s_proc[0] ){
 1830         int sio[2];
 1831         if( procSocket(ctx,sox->s_proc,sio) == 0 ){
 1832             commin = sio[0];
 1833             CommoutFd = sio[1];
 1834         }
 1835         Trace("PROC [%d,%d] %s",commin,CommoutFd,sox->s_proc);
 1836     }
 1837     if( commin < 0 && Infifo[0] ){
 1838         commin = open(Infifo,2);
 1839         Trace("COMMIN %d %s",commin,Infifo);
 1840     }
 1841     if( CommoutFd < 0 && Outfifo[0] ){
 1842         if( strcmp(Infifo,Outfifo) == 0 )
 1843             CommoutFd = commin;
 1844         else{
 1845             CommoutFd = open(Outfifo,2);
 1846             Trace("COMMOUT %d %s",CommoutFd,Outfifo);
 1847         }
 1848     }
 1849     if( commin < 0 )
 1850     if( 0 < isvport && !streq(isvhost,"-") && !streq(isvhost,"-.-") )
 1851     /* SERVER=sockmux://host:port given */
 1852     {
 1853         local[0] = 0;
 1854         sprintf(remote,"%s:%d",isvhost,isvport);
 1855         commin = CommoutFd = connects(ctx,AVStr(local),AVStr(remote),3);
 1856     }
 1857     if( commin < 0 && 0 < svport )
 1858     /* -Pport given */
 1859     {
 1860         int acto = ACC_TIMEOUT;
 1861         ACC_TIMEOUT = 0;
 1862         local[0] = remote[0] = 0;
 1863         commin = CommoutFd =
 1864             VSocket(ctx,"ACPT/SOX*",svsock,AVStr(local),AVStr(remote),"");
 1865         ACC_TIMEOUT = acto;
 1866         if( commin < 0 ){
 1867             Trace("ACPT %d = %d ERROR",svsock,commin);
 1868             /*
 1869             sleep(3);
 1870             */
 1871             if( CTX_withYY_CL(ctx) ){
 1872                 sv1log("----yySox-CL broken e%d\n",errno);
 1873                 _exit(0);
 1874             }
 1875             goto RETRY;
 1876         }
 1877         Trace("ACPT %d %s <- %s",commin,local,remote);
 1878         set_ClientSock(ctx,commin,remote,local);
 1879         set_keepalive(commin,1);
 1880         if( isPrivateSox(ctx) ){
 1881         }else
 1882         if( !source_permitted(ctx) ){
 1883             Trace("Forbidden %s",remote);
 1884             close(commin);
 1885             commin = -1;
 1886             goto RETRY;
 1887         }
 1888     }
 1889 
 1890 CONNDONE:
 1891     sox_init(sox,ctx,ac,av,&commin,&CommoutFd,AVStr(Serverurl),sizeof(Serverurl));
 1892     Trace("SOX reception[%d/%d] reserved(%d) channel[%d,%d]",
 1893         svport,svsock,sockc,commin,CommoutFd);
 1894 
 1895     if( commin < 0 ){
 1896         return -1;
 1897     }
 1898 
 1899     if( Nodelay )
 1900     set_nodelay(CommoutFd,1);
 1901 
 1902     if( 0 < file_issock(commin) ){
 1903         int fcl;
 1904         fcl = insertFCL(ctx,commin);
 1905         if( 0 <= fcl ){
 1906             Trace("Filter inserted: %d -> %d",fcl,commin);
 1907             Ocommin = commin;
 1908             commin = CommoutFd = fcl;
 1909         }
 1910     }
 1911     Comminfp = fdopen(commin,"r");
 1912     if( Comminfp == NULL ){
 1913         Trace("## cannot open %d\n",commin);
 1914         return -1;
 1915     }
 1916 
 1917     CFI_DISABLE = 1;
 1918     RES_CACHEONLY(1);
 1919 
 1920     for( ci = 0; ci < NSOCK; ci++ ){
 1921         Ap1 = &Agentbv[ci];
 1922         bzero(Ap1,sizeof(Agent));
 1923         Agentpv[ci] = Ap1;
 1924         Ap1->a_abid = ci;
 1925         Ap1->a_sock = -1;
 1926         Ap1->a_Laid = (Aid)-1;
 1927         Ap1->a_Xaid = (Aid)-1;
 1928         sox->s_aidactive[ci] = 0;
 1929     }
 1930     Agents = 0;
 1931 
 1932     Apn = newAgent(sox,-1,CommoutFd,SOX_COMMOUT);
 1933     Trace("L#%d %d COMMOUT",Apn->a_Laid,Apn->a_sock);
 1934 
 1935     Apn = newAgent(sox,-1,commin,SOX_COMMIN);
 1936     Trace("L#%d %d COMMIN(-P%d)",Apn->a_Laid,Apn->a_sock,
 1937         sockPort(0<=Ocommin?Ocommin:commin));
 1938 
 1939     if( lSINGLEP() ){
 1940     }else
 1941     if( sox_private ){
 1942         int getParentSock();
 1943         int fd;
 1944         if( 0 <= (fd = getParentSock()) ){
 1945             Apn = newAgent(sox,-1,fd,SOX_PARENT);
 1946         }
 1947     }
 1948 
 1949     /* must do exclusive lock here ... */
 1950     /*
 1951     wcc = send_HELLO(sox,&out,0,pack);
 1952     */
 1953     wcc = send_HELLO(sox,CommOutAp,0,pack);
 1954     if( CTX_withAuth(ctx) ){
 1955         extern int AccViaHTMUX;
 1956         if( AccViaHTMUX || sox->s_soxinports ){
 1957             Trace("#### Auth. for non-SockMux? %d %X",
 1958                 AccViaHTMUX,sox->s_soxinports);
 1959         }else
 1960         CommInAp->a_authstat = AUTH_REQ;
 1961     }
 1962 
 1963     stat = 0;
 1964     for( ci = 0; ci < 100; ci++ ){
 1965         double St;
 1966         /*
 1967         rcc = recvpack(sox,Comminfp,pack,0);
 1968         */
 1969         St = Time();
 1970         if( fPollIn(Comminfp,15*1000) == 0 ){
 1971             Trace("COMMIN error read() timeout");
 1972             close(CommoutFd);
 1973             /*
 1974             sleep(3);
 1975             */
 1976             goto RETRY;
 1977         }
 1978         Trace("--Sox setup %.2f",Time()-St);
 1979         rcc = recvpack(sox,CommInAp,Comminfp,pack,0);
 1980         if( rcc < (int)PHSIZE ){
 1981             Trace("COMMIN error read()=%d < %d",rcc,PHSIZE);
 1982             close(CommoutFd);
 1983             /*
 1984             sleep(3);
 1985             */
 1986             goto RETRY;
 1987         }
 1988         stat = pack->p_Type;
 1989         Trace("waiting HELLO V%02X > %02X",pack->p_Ver,stat);
 1990 
 1991         if( pack->p_Ver != MYVER ){
 1992             Trace("SockMux protocol version mismatch: %X / %X",
 1993                 pack->p_Ver,MYVER);
 1994             close(CommoutFd);
 1995             /*
 1996             sleep(3);
 1997             */
 1998             goto RETRY;
 1999         }
 2000 
 2001         if( stat == SOX_HELLO
 2002          || stat == SOX_HELLOOK
 2003         ){
 2004             if( stat == SOX_HELLOOK )
 2005                 got_HELLO(sox,CommInAp,pack);
 2006             else    Trace("Got HELLO");
 2007             /*
 2008             send_HELLO(sox,&out,1,pack);
 2009             */
 2010             send_HELLO(sox,CommOutAp,1,pack);
 2011 
 2012             if( stat == SOX_HELLOOK )
 2013                 break;
 2014         }
 2015     }
 2016     if( stat != SOX_HELLOOK ){
 2017         Trace("no HELLOOK");
 2018         return -1;
 2019     }
 2020 
 2021     send_PACKSIZE(sox,CommOutAp,pack);
 2022     if( !SOX_NOENCRYPT ){
 2023         if( 0 <= ToKey->k_group )
 2024             send_willCRYPT(sox,CommOutAp,pack,ToKey->k_group);
 2025         send_PING(sox,CommOutAp,pack); /* for test */
 2026     }
 2027     if( !SOX_NOCONNDATA )
 2028         send_doCONNDATA(sox,CommOutAp,pack);
 2029     if( s_rsap ){
 2030         send_BIND(sox,CommOutAp,pack,s_rsap,0);
 2031     }
 2032 
 2033     /*
 2034      * set Nonblocking after HELLO done, or do HELLO after PollIn()
 2035      */
 2036     /*
 2037     setNonblockingIO(CommoutFd,1);
 2038     */
 2039 
 2040     for( ci = 0; ci < sockc; ci++ ){
 2041         Apn = newAgent(sox,-1,sockv[ci],SOX_LISTEN);
 2042         Trace("L#%d %d PORT=%d",Apn->a_Laid,Apn->a_sock,portv[ci]);
 2043     }
 2044     return 0;
 2045 }
 2046 
 2047 static Sox *sox0;
 2048 static void (*savsigTERM)(int);
 2049 void sox_finish(){
 2050     if( sox0 ){
 2051         shutdownAgents(sox0);
 2052     }
 2053 }
 2054 static void sigTERM(int sig)
 2055 {
 2056     Trace("---- SIGTERM %d ----",sig);
 2057     if( sox0 )
 2058         shutdownAgents(sox0);
 2059     if( savsigTERM )
 2060         (*savsigTERM)(sig);
 2061     Finish(0);
 2062 }
 2063 void checkServerFinish(const char *fmt,...){
 2064     IStr(msg,128);
 2065     int ppid;
 2066     VARGS(8,fmt);
 2067 
 2068     if( lSINGLEP() ){
 2069         return;
 2070     }
 2071     if( !sox_private )
 2072         return;
 2073         
 2074     ppid = getppid();
 2075     if( procIsAlive(ppid) == 0 ){
 2076         sprintf(msg,fmt,VA8);
 2077         porting_dbg("## No parentServ[%d] %s",ppid,msg);
 2078         Finish(-1);
 2079     }
 2080 }
 2081 static int sox_clock1(Sox *sox,DGC*ctx);
 2082 int sox_mainX(int ac,const char *av[],DGC*ctx,int svsock,int svport,int insock,int inport);
 2083 int sox_main(int ac,const char *av[],DGC*ctx,int svsock,int svport)
 2084 {
 2085     return sox_mainX(ac,av,ctx,svsock,svport,-1,0);
 2086 }
 2087 int sox_mainX(int ac,const char *av[],DGC*ctx,int svsock,int svport,int insock,int inport)
 2088 {   Sox *sox;
 2089 /*
 2090 {   Sox soxb,*sox = &soxb;
 2091 */
 2092 
 2093     sv1log("START\n");
 2094     savsigTERM = Vsignal(SIGTERM,sigTERM);
 2095     savsigTERM = Vsignal(SIGINT, sigTERM);
 2096     Vsignal(SIGPIPE,sigPIPE);
 2097     Vsignal(SIGCONT,sigCONT);
 2098     sox = sox_setup1(ctx);
 2099     sox0 = sox;
 2100 START:
 2101     /*
 2102     if( sox_setup(ac,av,ctx,svsock,svport,sox) < 0 )
 2103     */
 2104     if( sox_setupX(ac,av,ctx,svsock,svport,sox,insock,inport) < 0 )
 2105         goto EXIT;
 2106 
 2107     Debug("---- START ----");
 2108     sox_init_done = 1;
 2109     Qfdset = 0;
 2110     for(;;){
 2111         if( sox_clock1(sox,ctx) < 0 )
 2112         if( oneTime )
 2113             goto EXIT;
 2114         else
 2115             goto START;
 2116     }
 2117 EXIT:
 2118     sv1log("DONE\n");
 2119     if( lSINGLEP() && Comminfp != NULL ){
 2120         sv1log("## Comminfp=%X/%d\n",p2i(Comminfp),fileno(Comminfp));
 2121         fcloseFILE(Comminfp);
 2122         Comminfp = 0;
 2123     }else
 2124     Finish(0);
 2125     return 0;
 2126 }
 2127 int service_sockmux(DGC*ctx,int _1,int _2,int fromC,int toC,PCStr(svproto),PCStr(svhost),int svport,PCStr(svpath))
 2128 { 
 2129     if( isPrivateSox(ctx) ){
 2130     }else
 2131     if( !source_permitted(ctx) ){
 2132         CStr(shost,128);
 2133         int sport;
 2134         sport = getClientHostPort(ctx,AVStr(shost));
 2135         sv1log("Forbidden %s:%d\n",shost,sport);
 2136         return -1;
 2137     }
 2138     sox_main(0,NULL,ctx,fromC,svport);
 2139     return 0;
 2140 }
 2141 
 2142 static void sox_fdset(Sox *sox);
 2143 static void sox_relay1(Sox *sox,Agent *Api,int sin,Packet *pack,int OOB);
 2144 static int sox_COMMIN(Sox *sox,Agent *Api,DGC*ctx,Packet *pack,int OOB);
 2145 
 2146 static int sox_clock1(Sox *sox,DGC*ctx)
 2147 {   int nready;
 2148     int rev[NSOCK];
 2149     int ri,rx;
 2150     Agent *Api;
 2151     Packet packb,*pack = &packb;
 2152     Packet oobpack;
 2153     int oobpushed = 0;
 2154     int Na1,Qfdc1=0,Qfdc2=0,Qfdc3=0; /* just for debugging */
 2155 
 2156     sox->s_clock++;
 2157     sox->s_time = time(0);
 2158 
 2159     if( Qfdset == 0 )
 2160         sox_fdset(sox);
 2161 
 2162     Debug("%d poll(%d/%d) S=%u/%u R=%u/%u",sox->s_clock,Qfdc,Agents,
 2163         Tsent,TsentN,Trecv,TrecvN);
 2164 
 2165     Na1 = Agents;
 2166     Qfdc1 = Qfdc;
 2167     if( 0 < ready_cc(Comminfp) ){
 2168         rx = -1;
 2169         for( ri = 0; ri < Qfdc; ri++ ){
 2170             rev[ri] = 0;
 2171             if( Qfdv[ri] == fileno(Comminfp) ){
 2172                 rx = ri;
 2173             }
 2174         }
 2175         if( 0 <= rx ){
 2176             ri = rx;
 2177             Api = Agentpv[Qcxv[ri]];
 2178             rev[ri] = PS_IN; 
 2179             goto COMMIN;
 2180         }
 2181     }
 2182 
 2183     if( Nopush ){
 2184         set_nopush(CommoutFd,0);
 2185         send(CommoutFd,"",0,0);
 2186     }
 2187     if( Cork ){
 2188         set_cork(CommoutFd,0);
 2189     }
 2190     Qfdc2 = Qfdc;
 2191     nready = PollInsOuts(10*1000,Qfdc,Qfdv,Qqev,rev);
 2192     if( nready < 0 ){
 2193         if( lSINGLEP() ){
 2194             for( ri = 0; ri < Qfdc; ri++ ){
 2195                 sv1log("## clock1 %d) [%d]%d\n",
 2196                     ri,Qfdv[ri],SocketOf(Qfdv[ri]));
 2197             }
 2198         }
 2199     }
 2200     if( Cork ){
 2201         set_cork(CommoutFd,1);
 2202     }
 2203     if( Nopush ){
 2204         set_nopush(CommoutFd,1);
 2205     }
 2206 
 2207     if( nready == 0 ){
 2208         checkServerFinish("clock1-A");
 2209         /*
 2210         Trace("poll(%d) = %d",Qfdc,0);
 2211         for( ri = 0; ri < Agents; ri++ ){
 2212             Api = Agentpv[ri];
 2213             Trace("L#%d R#%d stat=%X pending-R=%d,L=%d",
 2214                 Api->a_Laid,Api->a_Xaid,
 2215                 Api->a_stat,
 2216                 Api->a_pend,
 2217                 Api->a_lbuf.b_rem);
 2218         }
 2219         for( ri = 0; ri < 256; ri++ ){
 2220             if( sox->s_Rpstats[ri] ){
 2221                 Trace("%02X %d",ri,sox->s_Rpstats[ri]);
 2222             }
 2223         }
 2224         */
 2225         /*
 2226         nready = PollInsOuts(Qtimeout*1000,Qfdc,Qfdv,Qqev,rev);
 2227         */
 2228         if( Nopush ){
 2229             set_nopush(CommoutFd,0);
 2230             send(CommoutFd,"",0,0);
 2231         }
 2232         if( Cork ){
 2233             set_cork(CommoutFd,0);
 2234         }
 2235         Qfdc3 = Qfdc;
 2236         nready = PollInsOuts(20*1000,Qfdc,Qfdv,Qqev,rev);
 2237         if( Cork ){
 2238             set_cork(CommoutFd,1);
 2239         }
 2240         if( Nopush ){
 2241             set_nopush(CommoutFd,1);
 2242         }
 2243         if( nready == 0 ){
 2244             checkServerFinish("clock1-B");
 2245             if( 60 <= commInactive(sox) ){
 2246                 Trace("Comm seems inactive (%d)",Qfdc);
 2247                 Trace("Comm seems inactive (%d) %s",
 2248                     Qfdc,tstmp(sox));
 2249                 shutdownAgents(sox);
 2250                 return -1;
 2251             }
 2252             nsigPIPE = 0;
 2253             sox->s_time = time(0);
 2254             send_PING(sox,CommOutAp,pack);
 2255             if( 0 < nsigPIPE ){
 2256                 Trace("SIGPIPE when sending to CommOut");
 2257                 return -1;
 2258             }else   return 0;
 2259         }
 2260     }
 2261     if( nready <= 0 ){
 2262         Trace("TIMEOUT fdc=%d nready=%d %ds",
 2263             Qfdc,nready,time(0)-sox->s_time);
 2264         if( CTX_withYY_BROKEN(ctx) ){
 2265             sv1log("----yySox poll broken e%d\n",errno);
 2266             _exit(0);
 2267         }
 2268         for( ri = 0; ri < Qfdc; ri++ ){
 2269             sv1log("## clock1 %d) [%d]%d\n",
 2270                 ri,Qfdv[ri],SocketOf(Qfdv[ri]));
 2271         }
 2272         checkServerFinish("TIMEOUT");
 2273         return -1;
 2274     }
 2275 
 2276     for( ri = 0; ri < Qfdc; ri++ ){
 2277         Api = Agentpv[Qcxv[ri]];
 2278         if( rev[ri] == 0 )
 2279             continue;
 2280 
 2281         if( rev[ri] & (PS_HUP | PS_ERR) ){
 2282             Trace("## POLL_ERROR %x L#%d",rev[ri],Api->a_Laid);
 2283             Trace("## POLL_ERROR %X L#%d/%d/%d %d/%d (%d %d %d) %s",
 2284                 rev[ri],Api->a_Laid,Agents,Na1,
 2285                 ri,Qfdc,Qfdc1,Qfdc2,Qfdc3,tstmp(sox));
 2286             if( Api->a_stat == SOX_COMMIN ){
 2287                 shutdownAgents(sox);
 2288                 return -1;
 2289             }else{
 2290                 Trace("## CLOSE TOO MUCH POLL_ERROR*%d %x L#%d",
 2291                     Api->a_errs,rev[ri],Api->a_Laid);
 2292                 if( 100 < Api->a_errs++ ){
 2293                     dupclosed(Qfdv[ri]);
 2294                 }
 2295             }
 2296         }
 2297         if( rev[ri] & PS_OUT ){
 2298             int rem,sent;
 2299             rem = Api->a_lbuf.b_rem;
 2300             writesock(sox,Api,NULL);
 2301             if( sent = rem - Api->a_lbuf.b_rem ){
 2302                 pack->p_Type = SOX_SENT;
 2303                 PK_setRaid(pack,Api->a_Xaid);
 2304                 PK_setSaid(pack,Api->a_Laid);
 2305                 set_INT(pack,sent);
 2306                 writecomm(sox,CommOutAp,pack);
 2307                 Trace("## FLUSHED=%d L#%d stat=%X",
 2308                     sent,Api->a_Laid,Api->a_stat);
 2309                 if( Api->a_stat == SOX_CLOSED ){
 2310                     Trace("-- FLUSHED L#%d rem(%d/%d)",
 2311                         Api->a_Laid,sent,rem);
 2312                 }else
 2313                 Api->a_stat = SOX_SENT;
 2314                 Qfdset = 0;
 2315             }
 2316         }
 2317         if( (rev[ri] & (PS_IN|PS_PRI)) == 0 )
 2318             continue;
 2319 
 2320         if( Api->a_stat == SOX_PARENT ){
 2321             porting_dbg("## Owner Process Dead [%d] [%d]=%X",
 2322                 getppid(),Qfdv[ri],rev[ri]);
 2323             checkServerFinish("poll[%d]=%X",Qfdv[ri],rev[ri]);
 2324             Finish(0);
 2325         }
 2326 
 2327         if( Api->a_stat == SOX_COMMIN )
 2328         COMMIN:{
 2329         /* relay from remote to local */
 2330             if( rev[ri] & PS_PRI ){
 2331                 if( sox_COMMIN(sox,Api,ctx,pack,1) < 0 ){
 2332                     return -1;
 2333                 }
 2334             }
 2335             if( rev[ri] & PS_IN )
 2336                 if( sox_COMMIN(sox,Api,ctx,pack,0) < 0 )
 2337                     return -1;
 2338             continue;
 2339         }
 2340         if( Api->a_stat == SOX_LISTEN ){
 2341         /* accept at reception socket(s) */
 2342             sox_accept1(sox,ctx,Api,pack);
 2343             continue;
 2344         }
 2345         /* relay local sockets to remote */
 2346         if( rev[ri] & PS_PRI )
 2347         {
 2348             sox_relay1(sox,Api,Qfdv[ri],pack,1);
 2349             if( pack->p_Type == SOX_OOBPUSH ){
 2350                 oobpushed = 1;
 2351                 oobpack = *pack;
 2352             }
 2353         }
 2354         if( rev[ri] & PS_IN )
 2355         {
 2356             sox_relay1(sox,Api,Qfdv[ri],pack,0);
 2357         }
 2358         if( oobpushed )
 2359         {
 2360             sox_relay1(sox,Api,Qfdv[ri],&oobpack,2);
 2361         }
 2362     }
 2363     return 0;
 2364 }
 2365 
 2366 typedef struct {
 2367     int c_fd;
 2368     int c_tid;
 2369     const char *c_F;
 2370     int c_L;
 2371 } Close1;
 2372 static int closes[2] = {-1,-1};
 2373 int closetid;
 2374 int closei;
 2375 int closeo;
 2376 extern int THEXIT;
 2377 int stopcloseR(){
 2378     Close1 c1;
 2379     if( closetid && 0 <= closes[1] ){
 2380         c1.c_fd = -1;
 2381         c1.c_tid = 0;
 2382         IGNRETP write(closes[1],&c1,sizeof(c1));
 2383         return 1;
 2384     }
 2385     return 0;
 2386 }
 2387 int waitLock();
 2388 static int closeQ(){
 2389     int rdy;
 2390     int ci;
 2391     Close1 c1;
 2392     int rcc;
 2393     int wi;
 2394     int rcode;
 2395     double St,Now;
 2396 
 2397     for( ci = 0; ; ci++ ){
 2398         rdy = PollIn(closes[0],60*1000);
 2399         if( THEXIT ){
 2400             sv1log("-- closeR(%d) %d/%d rdy=%d TX=%d\n",
 2401                 ci,closeo,closei,rdy,THEXIT);
 2402             break;
 2403         }
 2404         if( rdy < 0 ){
 2405             sv1log("## closeR(%d) %d/%d rdy=%d\n",
 2406                 ci,closeo,closei,rdy);
 2407             break;
 2408         }
 2409         if( rdy == 0 ){
 2410             Verbose("-- closeR(%d) %d/%d rdy=%d\n",
 2411                 ci,closeo,closei,rdy);
 2412             continue;
 2413         }
 2414         rcc = read(closes[0],&c1,sizeof(c1));
 2415         if( rcc != sizeof(c1) ){
 2416             sv1log("## closeR(%d) %d/%d rdy=%d rcc=%d\n",
 2417                 ci,closeo,closei,rdy,rcc);
 2418             break;
 2419         }
 2420         closeo++;
 2421         wi = waitLock();
 2422         St = Time();
 2423         /* set the owner thread of the fd */
 2424         /*
 2425         waitShutdownSocket(c1.c_F,c1.c_L,c1.c_fd,3*1000);
 2426         */
 2427         rcode = close(c1.c_fd);
 2428         Now = Time();
 2429         sv1log("-- closeR(%d) %d/%d rco=%d [%d]%04X %d %.3f <= %s:%d\n",
 2430             ci,closeo,closei,rcode,c1.c_fd,PRTID(c1.c_tid),
 2431             wi,Now-St,c1.c_F,c1.c_L);
 2432     }
 2433     return ci;
 2434 }
 2435 static int byme(){
 2436     int ri;
 2437     if( closetid == 0 ){
 2438         closetid = -1;
 2439         return 1;
 2440     }
 2441     for( ri = 0; ri < 10; ri++ ){
 2442         if( closetid != -1 ){
 2443             break;
 2444         }
 2445         msleep(300);
 2446     }
 2447     sv1log("-- got closeQ %X (%d)\n",closetid,ri);
 2448     return 0;
 2449 }
 2450 int closeR(FL_PAR,int fd){
 2451     int rcode;
 2452     double St,Now;
 2453 
 2454     /*
 2455     if( lSINGLEP() )
 2456     */
 2457     if( INHERENT_thread() )
 2458     {
 2459         Close1 c1;
 2460         if( closetid == 0 ){
 2461             if( byme() ){
 2462             Socketpair(closes);
 2463             closetid = thread_fork(0x40000,0,"closeR",(IFUNCP)closeQ);
 2464             sv1log("-- created closeQ %X\n",PRTID(closetid));
 2465             }
 2466         }
 2467         c1.c_fd = fd;
 2468         c1.c_tid = getthreadid();
 2469         c1.c_F = FL_F;
 2470         c1.c_L = FL_L;
 2471         IGNRETP write(closes[1],&c1,sizeof(c1));
 2472         closei++;
 2473         return 0;
 2474     }
 2475     St = Time();
 2476     rcode = close(fd);
 2477     Now = Time();
 2478     if( 1 < Now-St ){
 2479         Trace("#### SLOW CLOSE [%d] %.3f",fd,Now-St);
 2480     }
 2481     return rcode;
 2482 }
 2483 
 2484 void sox_dumpFds(Sox *sox,PVStr(fds),int siz)
 2485 {   int i;
 2486     refQStr(sp,fds); /**/
 2487     Agent *Ap1;
 2488 
 2489     setVStrEnd(fds,0);
 2490     cpyQStr(sp,fds);
 2491     for( i = 0; i < Qfdc && i < 16; i++ ){
 2492         Ap1 = Agentpv[Qcxv[i]];
 2493         sprintf(sp,"%s#%d/%d/%d",i?",":"",Ap1->a_Laid,Qfdv[i],Qqev[i]);
 2494         sp += strlen(sp);
 2495     }
 2496 }
 2497 static void sox_fdset(Sox *sox)
 2498 {   int ci,cj;
 2499     Agent *Ap1;
 2500     int rcode;
 2501     int qev;
 2502 
 2503     for( ci = 0; ci < Agents; ci++ ){
 2504         Ap1 = Agentpv[ci];
 2505         if( Ap1->a_stat == SOX_CLOSED ){
 2506             if( 0 < Ap1->a_lbuf.b_rem ){
 2507                 if( Ap1->a_ltCLOSED == 0 )
 2508                 if( Llinger < sox->s_time - Ap1->a_rtCLOSED ){
 2509                     Trace("-- Timeout close L#%d rem(%d)",
 2510                         Ap1->a_Laid,Ap1->a_lbuf.b_rem);
 2511                 }else{
 2512                     Trace("-- Delay close L#%d rem(%d)",
 2513                         Ap1->a_Laid,Ap1->a_lbuf.b_rem);
 2514                     continue;
 2515                 }
 2516             }
 2517             /*
 2518             rcode = close(Ap1->a_sock);
 2519             */
 2520             rcode = closeR(FL_ARG,Ap1->a_sock);
 2521 /*
 2522     Trace("Fin L#%d[%d]%d S=%d/%d P=%d/%d R=%d/%d S,R=%d/%d,%d/%d",
 2523 */
 2524     Trace("Fin L#%d[%d]%d S=%d/%d P=%d/%d R=%d/%d S,R=%d/%d,%d/%d (%.3f)",
 2525                 Ap1->a_Laid,Ap1->a_abid,Ap1->a_sock,
 2526                 Ap1->a_sent,Ap1->a_sentN,
 2527                 Ap1->a_pendN,TpendN,
 2528                 Ap1->a_recv,Ap1->a_recvN,
 2529 /*
 2530                 Tsent,TsentN,Trecv,TrecvN
 2531 */
 2532                 Tsent,TsentN,Trecv,TrecvN,
 2533                 Time() - Ap1->a_start
 2534             );
 2535             Ap1->a_sock = -1;
 2536 
 2537             if( Ap1->a_pid ){
 2538                 int pid;
 2539                 while( 0 < (pid = NoHangWait()) ){
 2540                     Trace("Exit pid=%d",pid);
 2541                     /*
 2542                     TOTAL_SERVED++;
 2543                     */
 2544                     *pTOTAL_SERVED += 1;
 2545                     NUM_CHILDREN--;
 2546                     putLoadStat(ST_DONE,1);
 2547                     put_svstat();
 2548                 }
 2549             }
 2550             sox->s_aidactive[Ap1->a_Laid] = 0;
 2551             delAgent(sox,ci);
 2552         }
 2553     }
 2554     Qfdc = 0;
 2555     for( ci = 0; ci < Agents; ci++ ){
 2556         Ap1 = Agentpv[ci];
 2557         qev = 0;
 2558 
 2559         if( Ap1->a_stat != SOX_COMMOUT )
 2560         if( Ap1->a_stat != SOX_CONNECT )
 2561         if( Ap1->a_stat != SOX_CLOSE )
 2562         if( Ap1->a_stat != SOX_SENDING )
 2563         if( Ap1->a_stat != SOX_SENDINGOOB )
 2564         {
 2565             qev |= (PS_IN | PS_PRI);
 2566         }
 2567         if( Ap1->a_lbuf.b_rem ){
 2568             qev |= PS_OUT;
 2569         }
 2570         if( qev ){
 2571             Qcxv[Qfdc] = ci;
 2572             Qfdv[Qfdc] = Agentpv[ci]->a_sock;
 2573             Qqev[Qfdc] = qev;
 2574             Qfdc++;
 2575         }
 2576     }
 2577     Qfdset = 1;
 2578 }
 2579 static void sox_relay1(Sox *sox,Agent *Api,int sin,Packet *pack,int OOB)
 2580 {   int wcc;
 2581 
 2582     if( Api->a_stat == SOX_CLOSE || Api->a_stat == SOX_CLOSED ){
 2583         Trace("Closing> L#%d[%X] -> R#%d[SEND] ignored",
 2584             Api->a_Laid,Api->a_stat,Api->a_Xaid);
 2585         Qfdset = 0;
 2586         return;
 2587     }
 2588 
 2589     wcc = sock2comm(sox,Api,sin,CommOutAp,pack,OOB);
 2590     if( wcc == 0 && pack->p_Type == SOX_OOBPUSH ){
 2591         return;
 2592     }else
 2593     if( 0 < wcc ){
 2594         /*
 2595         Api->a_sent += PK_Leng(pack);
 2596         Api->a_sentN++;
 2597         */
 2598         Api->a_rpend += PK_Leng(pack);
 2599         if( OOB ){
 2600             TpendN++;
 2601             Api->a_pendN++;
 2602             Api->a_stat = SOX_SENDINGOOB;
 2603         }else{
 2604             /*
 2605             if( PWSIZE*MAXPENDING < Api->a_rpend ){
 2606             */
 2607             if( PackSize*PqueSize < Api->a_rpend ){
 2608                 TpendN++;
 2609                 Api->a_pendN++;
 2610                 Api->a_stat = SOX_SENDING;
 2611             }else   Api->a_stat = SOX_SEND;
 2612         }
 2613         Qfdset = 0;
 2614         Debug("SEND> L#%d -> R#%d (%d) pending=%d",
 2615             Api->a_Laid,Api->a_Xaid,PK_Leng(pack),Api->a_rpend);
 2616     }else
 2617     if( errno == EAGAIN ){
 2618         Trace("EAGAIN for read()");
 2619     }else{
 2620         Api->a_stat = SOX_CLOSE;
 2621         if( 0 < Api->a_lbuf.b_rem ){
 2622             Trace("##CLOSE>## L#%d discard pending output(%d)",
 2623                 Api->a_Laid,Api->a_lbuf.b_rem);
 2624             Api->a_lbuf.b_rem = 0;
 2625         }
 2626         Qfdset = 0;
 2627 
 2628         pack->p_Type = SOX_CLOSE;
 2629         PK_setSaid(pack,Api->a_Laid);
 2630         PK_setRaid(pack,Api->a_Xaid);
 2631         set_STR(pack,"DO close");
 2632         writecommX(sox,Api,CommOutAp,pack);
 2633         Trace("CLOSE> L#%d -> R#%d (rcc=%d errno=%d)",
 2634             Api->a_Laid,Api->a_Xaid, wcc,errno);
 2635     }
 2636 }
 2637 static int sox_COMMIN(Sox *sox,Agent *Api,DGC*ctx,Packet *pack,int OOB)
 2638 {   int rcc;
 2639     int stat;
 2640     Agent *ApR,*Apn;
 2641     int pid;
 2642     int ci;
 2643     int clsock;
 2644     int aid;
 2645     CStr(local,256);
 2646     CStr(remote,256);
 2647     CStr(pair,512);
 2648     int wcc;
 2649     int ostat;
 2650 
 2651     /*
 2652     rcc = recvpack(sox,Comminfp,pack,OOB);
 2653     */
 2654     rcc = recvpack(sox,Api,Comminfp,pack,OOB);
 2655     if( rcc < 0 ){
 2656         shutdownAgents(sox);
 2657         return -1;
 2658     }
 2659     stat = pack->p_Type;
 2660     sox->s_Rpstats[stat] += 1;
 2661 
 2662     ApR = 0;
 2663     for( ci = 0; ci < Agents; ci++ ){
 2664         if( Agentpv[ci]->a_Laid == PK_Raid(pack) ){
 2665             ApR = Agentpv[ci];
 2666             if( (stat & SOX_ACK) == 0 ){
 2667                 ApR->a_recv += PK_Leng(pack);
 2668                 ApR->a_recvN++;
 2669             }
 2670             ApR->a_stats.s_time = sox->s_time;
 2671             break;
 2672         }
 2673     }
 2674     if( 1 < dbglev ){
 2675         Trace("recvpack L#%d[%02X] <- R#%d[%02X] %d/%d/%d",
 2676             ApR?ApR->a_Laid:-1,ApR?ApR->a_stat:0,
 2677             PK_Said(pack)!=0xFFFF?PK_Said(pack):-1,stat,
 2678             PK_Leng(pack),ApR?ApR->a_recv:0,ApR?ApR->a_recvN:0);
 2679     }
 2680 
 2681     if( ApR )
 2682     if( ApR->a_stat == SOX_CLOSE || ApR->a_stat == SOX_CLOSED )
 2683     /* ignore packets arrived during closing */
 2684     {
 2685         if( stat != SOX_CLOSED && stat != SOX_CLOSE ){
 2686             Trace("Closing< L#%d[%X] <- R#%d[%X] ignored",
 2687                 PK_Raid(pack),ApR->a_stat,PK_Said(pack),stat);
 2688             return 0;
 2689         }
 2690     }
 2691 
 2692     if( CommInAp->a_authstat & AUTH_REQ )
 2693     if( (CommInAp->a_authstat & AUTH_OK) == 0 ){
 2694         switch( stat ){
 2695             case SOX_CONNECT:
 2696             case SOX_BIND:
 2697                 Trace("NOT AUTHENTICATED");
 2698                 pack->p_Type = SOX_CLOSE;
 2699                 PK_setRaid(pack,PK_Said(pack));
 2700                 PK_clrSaid(pack);
 2701                 set_STR(pack,"### Not Authenticated ###");
 2702                 wcc = writecomm(sox,CommOutAp,pack);
 2703                 return -1;
 2704         }
 2705     }
 2706 
 2707     switch( stat ){
 2708     case -1:
 2709         Trace("BROKEN CONNECTION");
 2710         /* broken connection */
 2711         return -1;
 2712 
 2713     case SOX_NOOP:
 2714         {
 2715         CStr(stime,64);
 2716         getTimestamp(AVStr(stime));
 2717         Trace("Got NOOP %s #%d",stime,TrecvN);
 2718         break;
 2719         }
 2720     case SOX_ECHO:
 2721         Debug("Got ECHO [%u]",get_INT(pack));
 2722         send_ACK(sox,CommOutAp,pack);
 2723         break;
 2724     case SOX_ECHOOK:
 2725         Debug("Got ECHO [%u] OK",get_INT(pack));
 2726         break;
 2727 
 2728     case SOX_HELLO:
 2729         Trace("HELLO");
 2730         shutdownAgents(sox);
 2731         return -1;
 2732 
 2733     case SOX_HELLOOK:
 2734         got_HELLO(sox,Api,pack);
 2735         break;
 2736 
 2737     case SOX_SETOPT:
 2738         Trace("Got SETOPT [%X][%X]+%d",
 2739             pack->p_data[0],0xFF&pack->p_data[1],PK_Leng(pack));
 2740         if( pack->p_data[0] == SOX_O_PACKSIZE ){
 2741             set_PACKSIZE(sox,Api,pack);
 2742         }else
 2743         if( pack->p_data[0] == SOX_O_CRYPT )
 2744         {
 2745             set_CRYPT(sox,Api,pack);
 2746             send_PASS(sox,Api,pack);
 2747         }
 2748         else
 2749         if( pack->p_data[0] == SOX_O_CONNDATA ){
 2750             if( !SOX_NOCONNDATA ){
 2751                 Trace("CONNECT+DATA enabled");
 2752                 DO_CONNDATA = 1;
 2753             }
 2754         }
 2755         else
 2756         if( pack->p_data[0] == SOX_O_AUTH ){
 2757             recv_AUTH(sox,Api,pack);
 2758         }
 2759         break;
 2760     case SOX_CRYPTON:
 2761         Trace("Got CRYPTON: %d",pack->p_data[0]);
 2762         getCryptPreamble(sox,Api,pack);
 2763         break;
 2764 
 2765     case SOX_CONNECT:
 2766         Debug("Connect< R#%d[%s]",PK_Said(pack),pack->p_data);
 2767         clsock = sox_connect1(optctx(ctx),ctx,pack,Serverurl,AVStr(remote),AVStr(local),&pid);
 2768         if( clsock < 0 )
 2769             goto SOXCLOSE;
 2770 
 2771         if( 0 <= clsock ){
 2772             put_conndata(pack,clsock);
 2773             setNonblockingIO(clsock,1);
 2774             set_nodelay(clsock,1);
 2775             Apn = newAgent(sox,PK_Said(pack),clsock,SOX_CONNECTED);
 2776             aid = Apn->a_Laid;
 2777             Apn->a_remote = 1;
 2778             Apn->a_pid = pid;
 2779             Qfdset = 0;
 2780             Trace("Connected %d L#%d[%s] <- R#%d[%s]",
 2781                 clsock,aid,local,PK_Said(pack),pack->p_data);
 2782             PK_setRaid(pack,Apn->a_Laid);
 2783             set_CONNECT(Apn,pack,remote,local);
 2784             get_conndata(sox,Apn,pack);
 2785             send_ACK(sox,CommOutAp,pack);
 2786         }else SOXCLOSE:{
 2787             pack->p_Type = SOX_CLOSE;
 2788             PK_setRaid(pack,PK_Said(pack));
 2789             PK_clrSaid(pack);
 2790             set_STR(pack,"No server");
 2791             wcc = writecomm(sox,CommOutAp,pack);
 2792         }
 2793         break;
 2794 
 2795     case SOX_CONNECTED:
 2796         Trace("CONNed< L#%d <- R#%d[%s]",
 2797             PK_Raid(pack),PK_Said(pack),pack->p_data);
 2798         if( ApR ){
 2799             put_conndata(pack,ApR->a_sock);
 2800             ApR->a_Xaid = PK_Said(pack);
 2801             ApR->a_stat = SOX_CONNECTED;
 2802             Qfdset = 0;
 2803 
 2804 /*
 2805 reserve port for BIND (data connection) for each CONNECT
 2806 L#NL BIND PL
 2807 R#NR BIND PR
 2808 FTP resp. PORT PL
 2809 accept at PL by L#NL
 2810 forward to R#NR
 2811 R#NR connect to PR
 2812 ready L#NL and R#NR
 2813 
 2814 STRCPY(rsvdport,"*:*");
 2815 sock = VSocket(ctx,"BIND/SOX",-1,AVSTR(rsvdport),AVSTR(remote),"listen=1");
 2816 Apb = newAgent(sox,-1,sock,SOX_LISTEN);
 2817 Apn->a_remote = 0;
 2818 Qfdset = 0;
 2819 
 2820 or run SERVER=ftp at the entrance ?
 2821 */
 2822         }
 2823         break;
 2824 
 2825     case SOX_SENDOOB:
 2826         if( ApR ){
 2827             wcc = sendOOB(ApR->a_sock,pack->p_data,PK_Leng(pack));
 2828             Trace("SendOOB< L#%d <- R#%d (%d/%d)",
 2829                 PK_Raid(pack),PK_Said(pack),wcc,PK_Leng(pack));
 2830             set_INT(pack,wcc);
 2831             send_ACK(sox,CommOutAp,pack);
 2832         }else{
 2833             /* remove the obsolete remote agent by SOX_CLOSED */
 2834         }
 2835         break;
 2836 
 2837     case SOX_SENTOOB:
 2838         if( ApR ){
 2839             int sent = get_INT(pack);
 2840             Trace("SENTOOB< L#%d/%X <- R#%d (%d) pending-R=%d,L=%d",
 2841                 PK_Raid(pack),ApR->a_stat,PK_Said(pack),sent,
 2842                 ApR->a_rpend,ApR->a_lpend);
 2843             ApR->a_stat = SOX_SENTOOB;
 2844             ApR->a_rpend -= sent;
 2845             Qfdset = 0;
 2846         }
 2847         break;
 2848 
 2849     case SOX_SEND:
 2850         Debug("Send< L#%d <- R#%d",PK_Raid(pack),PK_Said(pack));
 2851         if( ApR ){
 2852             if( ApR->a_stat == SOX_CLOSE ){
 2853                 Trace("##Send<## L#%d(CLOSED) R%d discard(%d)",
 2854                 PK_Raid(pack),PK_Said(pack),PK_Leng(pack));
 2855                 break;
 2856             }
 2857             wcc = writesock(sox,ApR,pack);
 2858             if( wcc <= 0 ){
 2859                 break;
 2860             }
 2861             set_INT(pack,wcc);
 2862             if( !OOB )
 2863             send_ACK(sox,CommOutAp,pack);
 2864         }else{
 2865             /* return SOX_CLOSED */
 2866         }
 2867         break;
 2868 
 2869     case SOX_SENT:
 2870         if( ApR ){
 2871             int sent = get_INT(pack);
 2872             ApR->a_rpend -= sent;
 2873             /*
 2874             if( ApR->a_rpend < PWSIZE*MAXPENDING ){
 2875             */
 2876             if( ApR->a_rpend < PackSize*PqueSize ){
 2877                 if( ApR->a_stat == SOX_SENDING ){
 2878                     Debug("## RESUMED> L#%d",ApR->a_Laid);
 2879                 }
 2880                 ApR->a_stat = SOX_SENT;
 2881                 Qfdset = 0;
 2882             }
 2883             Debug("SENT< L#%d <- R#%d (%d) pending=%d",
 2884             PK_Raid(pack),PK_Said(pack),sent,ApR->a_rpend);
 2885         }else{
 2886             /* return SOX_CLOSED */
 2887         }
 2888         break;
 2889 
 2890     case SOX_CLOSE:
 2891         if( pack->p_data[0] == '#' ){
 2892         Trace("Close< L#%d <- R#%d [%s]",PK_Raid(pack),PK_Said(pack),
 2893             pack->p_data);
 2894         }else
 2895         Trace("Close< L#%d <- R#%d",PK_Raid(pack),PK_Said(pack));
 2896         ostat = 0;
 2897         if( ApR ){
 2898             ostat = ApR->a_stat;
 2899             ApR->a_stat = SOX_CLOSED;
 2900             ApR->a_rtCLOSED = sox->s_time;
 2901             Qfdset = 0;
 2902         }
 2903         if( ostat == SOX_CLOSE ){
 2904             Trace("Close: simultaneous close from both side");
 2905         }else{
 2906         set_STR(pack,"OK closed");
 2907         send_ACK(sox,CommOutAp,pack);
 2908         }
 2909         break;
 2910 
 2911     case SOX_CLOSED:
 2912         Trace("CLOSED< L#%d <- R#%d",PK_Raid(pack),PK_Said(pack));
 2913         if( ApR ){
 2914             ApR->a_stat = SOX_CLOSED;
 2915             Qfdset = 0;
 2916         }
 2917         break;
 2918 
 2919     case SOX_BIND:
 2920         Trace("BIND< L#%d <- R#%d %s",PK_Raid(pack),PK_Said(pack),
 2921             pack->p_data);
 2922         recv_BIND(sox,CommOutAp,pack);
 2923         break;
 2924     case SOX_BINDOK:
 2925         Trace("BIND> L#%d <- R#%d %s",PK_Raid(pack),PK_Said(pack),
 2926             pack->p_data);
 2927         recv_BOUND(sox,pack);
 2928         break;
 2929 
 2930     default:
 2931         Trace("unknown %d",stat);
 2932         break;
 2933     }
 2934     return 0;
 2935 }
 2936 
 2937 #endif /*} OPT_S */
 2938 
 2939 /* '"DIGEST-OFF"' */
 2940