/* code to allow nos to talk directly to bpqcode
 *
 * by paul h launspach n5faz
 * (c) 1993,1994 FazCom
 * 4-13-93
 */
/* $Id: bpqcmd.c 1.4 1994/03/11 15:25:06 fz-phl Exp $ */
/* $Log: bpqcmd.c $
 * Revision 1.4  1994/03/11  15:25:06  fz-phl
 * added ifdef BPQJNOS for printf -> tprintf macro and
 * changed display of ifp-rawsndcnt to a %lu in dobpqstat.
 *
 * Revision 1.3  1994/03/11  15:13:45  Johan
 * changed printf's to tprintf's
 *
 * Revision 1.2  1994/03/11  15:04:33  fz-phl
 * added ifdef BPQSOCK and other stuff for jnos.
 *
 * Revision 1.1  1994/03/11  02:25:10  fz-phl
 * Initial revision
 *
 */
#include "global.h"
#include "config.h"
#ifdef BPQ
#include "cmdparse.h"
#include "socket.h"
#include "session.h"
#include "usock.h"
#include "bpq.h"
  
#ifdef BPQJNOS          /* change printf to tprintf for jnos etc */
#define printf tprintf
#endif
  
#ifdef BPQSOCK
static int dobpqstat (int,char *argv[],void *);
static int dobpqconn (int,char *argv[],void *);
static int dobpqreset (int,char *argv[],void *);
static int dobpqwindow (int,char *argv[],void *);
#endif
  
char *Bpqstates[] = {
    "Disconn",
    "Connect",
    "Listen",
    "Lis>Con"
};
  
char *Bpqreasons[] = {
    "Normal",
    "By Peer",
    "Timeout",
    "Reset",
    "Refused"
} ;
  
#ifdef BPQSOCK
static struct cmds Bpqcmds[] = {
    "connect",      dobpqconn,  1024, 0, NULLCHAR,
    "reset",        dobpqreset, 0, 2, "bpq reset <bpqcb>",
    "stat",         dobpqstat,  0, 0, NULLCHAR,
    "window",       dobpqwindow, 0, 1, "bpq window <frames>",
    NULLCHAR,
};
  
/* Multiplexer for top-level bpq command */
int
dobpq(argc,argv,p)
int argc;
char *argv[];
void *p;
{
    if(argc < 2)
        return dobpqstat(argc,argv,p);
    return subcmd(Bpqcmds,argc,argv,p);
}
#endif */ BPQSOCK */
  
/* display bpq info stats */
#ifdef BPQSOCK
static
#endif
int
dobpqstat(argc,argv,p)
int argc;
char *argv[];
void *p;
{
    int i;
    struct iface *ifp;
#ifdef BPQSOCK
    struct bpq_cb *cb;
#endif
    char buf[11];
  
    if(!Bpqinfo.vec){
        printf("Bpq must be initialized with: attach bpq init <vec> <stream>\n");
        return 1;
    }
  
    printf("Vec Stream Ports Window Conn: Tot Max Curr Next\n");
    printf(" %2x     %2u    %2u     %2u       %3u %3u  %3u  %3u\n",
    Bpqinfo.vec,Bpqinfo.monstream,Bpqinfo.maxport,Bpqinfo.window,
    Bpqinfo.maxstream-Bpqinfo.monstream + 1,
    Bpqinfo.maxconn,Bpqinfo.curr,Bpqinfo.nextconn+1);
  
    printf("Recvd  Sent    Rx    Tx   Rxint   Txint  Ctlint Free Min\n");
    printf("%5lu %5lu %5lu %5lu %7lu %7lu %7lu",
    Bpqinfo.recv,Bpqinfo.send,Bpqinfo.recvcnt,
    Bpqinfo.sendcnt,Bpqinfo.rxcnt,Bpqinfo.txcnt,
    Bpqinfo.contcnt);
    i = bpq_int(BPQ_BUF,1,0,NULLCHAR);
    Bpqinfo.minfree = min(i,Bpqinfo.minfree);
    printf("  %3u %3u\n",i,Bpqinfo.minfree);
  
    /* print any iface info */
    if(Bpqinfo.maxport){
        printf("\nPort Lable      Call      IP-Address      Mtu    Rx    Tx\n");
        for(i=0; i < BPQMAXPORT ; i++)
            if((ifp = Bpqinfo.ports[i]) != NULLIF)
                printf("%4u %-10.10s %-9.9s %-15.15s %3u %5lu %5lu\n",ifp->dev,
                ifp->name,pax25(buf,ifp->hwaddr),inet_ntoa(ifp->addr),
                ifp->mtu,ifp->rawrecvcnt,ifp->rawsndcnt);
    }
  
    /* print any connection status */
#ifdef BPQSOCK
    if(Bpqinfo.cb != NULLBPQ){
        printf("\n&BPQCB   Owner            Sock St Num Recv Sent  Rxq  Txq Appl Tot Curr\n");
        for(cb = Bpqinfo.cb; cb != NULLBPQ ; cb = cb->next)
            st_bpq_cb(cb);
    }
#endif
    /* print the all stream status */
    /* whether we are using it or something else is */
    printf("\n St Num State       Type/Pt User      Recv Unak Maxf Pacl\n");
    for(i=1; i <= BPQMAXSTREAM ; i++)
        st_bpq(i);
  
    return 0;
}
  
#ifdef BPQSOCK
void
st_bpq_cb(cb)
struct bpq_cb *cb;
{
    struct usock *up;
  
    up = itop(cb->user);
    printf("%-8lx %-16.16s %4u %2u %3u %4u %4u %4u %4u",
    ptol(cb),up->owner->name,cb->user,cb->stream,cb->conn,
    cb->recv,cb->send,len_p(cb->rxq),len_q(cb->txq));
    if(cb->serv != NULLBPQS)
        if(cb->state == BPQ_ST_LIS)
            printf("   %2u %3u  %3u",cb->serv->appl,
            cb->serv->users,cb->serv->curr);
        else
            printf("           %3u",cb->sconn);
    printf("\n");
}
#endif
  
void
st_bpq(i)
int i;
{
#ifdef BPQSOCK
    struct bpq_cb *cb;
#endif
    char buf[11];
    uint16 st;
    uint16 tp;
  
        /* dont ack the state call. we want who ever is */
        /* really using this stream to see any state changes  */
        /* only display  active streams */
  
#ifdef BPQSOCK
    cb = find_bpq(i);
    st = bpq_int(BPQ_STATE,i,0,NULLCHAR);
    if(!st && cb == NULLBPQ && i != Bpqinfo.monstream)
        return;
#else
    if(!(st = bpq_int(BPQ_STATE,i,0,NULLCHAR)) && i != Bpqinfo.monstream)
        return;
#endif
  
#ifdef BPQSOCK
    if(cb != NULLBPQ){
        st |= cb->state;
        printf("%s%2u %3u",i == Bpqinfo.monstream ? "*" : " ",
        cb->stream,cb->conn);
    } else
#endif
        printf("%s%2u    ",i == Bpqinfo.monstream ? "*" : " ",i);
  
    printf(" %-7s%s",Bpqstates[st & ~BPQ_ST_CHG],
    st & BPQ_ST_CHG ? "+" : " ");
  
    if(st & BPQ_ST_CON){
        tp = bpq_int(BPQ_USERCALL,i,0,buf);
        if(tp & BPQ_HOST)
            printf("    Host");
        else if(tp & BPQ_SESSION)
            printf(" Circuit");
        else if(tp & BPQ_UPLINK)
            printf("  Uplink");
        else if(tp & BPQ_DOWNLK)
            printf(" Downlnk");
        else if(tp)
            printf(" Unk: %2u");
        else printf("        ");
        if(tp & BPQ_L2)
            printf(" %2u",lobyte(tp));
        else printf("   ");
#ifdef BPQSOCK
        if(cb != NULLBPQ)
            printf(" %9.9s  %3u  %3u  %3u  %3u",buf,
            bpq_int(BPQ_RECVQUE,i,0,NULLCHAR),cb->unack,
            cb->maxframe,cb->paclen);
        else
#endif
            printf(" %9.9s  %3u  %3u  %3u  %3u",buf,
            bpq_int(BPQ_RECVQUE,i,0,NULLCHAR),
            bpq_int(BPQ_UNACK,i,0,NULLCHAR),
            bpq_int(BPQ_MAXFR,i,0,buf),
            bpq_int(BPQ_PACLEN,i,0,buf));
    }
    printf("\n");
}
  
#ifdef BPQSOCK
static int
dobpqconn(argc,argv,p)
int argc;
char *argv[];
void *p;
{
    struct sockaddr_bq fsocket;
    struct session *sp;
    int s;
  
    if((sp = newsession(Cmdline,BPQSESSION,1)) == NULLSESSION){
        printf("Too many sessions\n");
        return 1;
    }
    if((s = socket(AF_BPQ,SOCK_STREAM,0)) == -1){
        printf("Can't create socket\n");
        freesession(sp);
        keywait(NULLCHAR,1);
        return 1;
    }
    fsocket.bpq_family = AF_BPQ;
    memcpy(fsocket.bpq_addr,"SWITCH   \0",AXBUF);
    sp->network = fdopen(s,"r+t");
    setvbuf(sp->network,NULLCHAR,_IOLBF,BUFSIZ);
    return tel_connect(sp, (char *)&fsocket, sizeof(struct sockaddr_bq));
}
  
static int
dobpqreset(argc,argv,p)
int argc;
char *argv[];
void *p;
{
    struct bpq_cb *cb;
  
    cb = (struct bpq_cb *)ltop(htol(argv[1]));
    if(!bpqval(cb)){
        printf(Notval);
        return 1;
    }
    disc_bpq(cb,1);
    return 0;
}
  
static int
dobpqwindow(argc,argv,p)
int argc;
char *argv[];
void *p;
{
    return setshort(&Bpqinfo.window,"Bpq window (frames)",argc,argv);
}
#endif /* BPQSOCK */
  
#endif /* BPQ */
  
