| |
|
|
|
NanoTst
|
I wrote this little program to test Nanos with an ethernet shield.
It uses my infrastructure with an additional lib for Multiple Architecture Networking (maTcp.h).
The MultiArch stuff was written when I was talking between my AMD Ryzen Linux workstation and an Rpi3.
It formats up an all ASCII message then sends it, via Tcp to the Gateway (Nano).
When the response returns, it displays the response on the console.
The Multi Architecture TCP package is patterend after Inf drivers.
It uses the same type control blocks etc.
It also uses non-blocking socket I/O and the Inf's ioWait() and ioRegWat(), ioSetWatOut(), and ioClrWatOut() calls.
I didn't spend any time cleaning this up so it may have a little ugliness.
05/28/22: Page Origin
nanoTst.c
/*H**********************************************************************
* Comm with Nano via Ethernet
*H**********************************************************************/
#include "inf.h"
#include "maTcp.h"
#include "includes.h"
// ================= DEFINES ===============================
#define RDBUFSIZ 8192
#define NL '\n';
// ================ PROTOTYES ==============================
static int reqClt( char *buf );
static int init( int argc, char *argv[] ); // "shopGwy envDev port"
// ============= GLOBAL VARIABLES ===========================
static int Waitim =2000, CltHndl, Port;
static char *RmtDev = "nano.0:4001"; // "nano.0:80"; // "host:port"
/***********************************************************************
*DESC:
*RTRN:
***********************************************************************/
static int
init( int argc, char *argv[] )
{
ioWatInit( argc, argv ); // INITIALIZE INF's Io Wait
return( OK );
}
/***********************************************************************
*DESC:
*RTRN:
***********************************************************************/
int
main( int argc, char *argv[] )
{
int len;
char *msg, *resp, msgBuf[STRMAX], rmtHost[STRMAX];
init( argc, argv );
utSetLvl( NULL, "55" ); // YOU CAN: export TRC_ENA=55 overrides utSetLvl
while( 1 )
{
utTrc(25,"main: about to open\n");
if( (CltHndl = ipOpnClt( RmtDev )) <0 ) // OPEN CONNECTION
utFatal( "ipOpnClt failed");
utTrc(25,"main: opened OK, Hndl: %d\n", CltHndl);
sprintf( msgBuf, "ENV\n" ); // FORMAT REQUEST ASCII MSG
len = reqClt( msgBuf ); // ENV REQUEST TO SERVER
utTrc( 25,"main, reqClt rtnd %d\n", len);
utTrc( 25,"Rcvd: [%s], dLen:%d", msgBuf, len );
printf( "Rcvd: [%s]\n", msgBuf ); // PRINT RETURN MSG
ipClose( CltHndl ); // CLOSE CONNECTION
utTrc( 25,"about to wait" );
if( strncmp( msgBuf, "ERR", 3 ))
utTrcErr("Bad Response: [%s]", msgBuf);
ioWait( 1000 );
}
}
/***********************************************************************
*DESC: SEND/RECEIVE MSG TO ENV SERVER
*RTRN: DLEN else ERR
***********************************************************************/
static int
reqClt( char *mp )
{
int rxCnt =0;
ulong end;
char *cp;
utTrc( 25,"Bgn" );
printf( "reqClt: sending [%s]\n", mp );
ipWt( CltHndl, mp, 4 ); // SEND REQUEST TO GATEWAY
*mp =0; // CLEAR (TRUNCATE) BUFFER
utTrc( 25,"Tx OK, About to enter while" );
while( 1 )
{ // WAIT FOR RESPONSE
utTrc( 25,"Tx OK, About to wait for response" );
if( ioWait( 400 ) == OK )
{ // WAIT FOR MESSAGE TO RETURN
if( (rxCnt = ipRd( CltHndl, mp )) <= 0 ) // READ
return( utTrcErr("Srv Rd Err or Timout, RxCnt: %d", rxCnt));
if( cp = fndChr( mp, 10 )) // FIND NL AT END
*cp = ']'; // REPLACE NL WITH RT BRKT FOR PRINT
utTrc( 25,"RdCmplt, Len: %d, [%s", rxCnt, mp );
break;
}
else
{
utTrcErr("Timeout");
break;
}
}
// ipClose( CltHndl );
utTrc( 25,"End, Len: %d, [%s]", rxCnt, mp );
return( rxCnt );
}
maTcp.c
/*******************************************************************
* USES TCP SOCKETS TO TRANSFER ASCII MSGS TO OTHER PROCESSES
* ASCII MSGES ONLY, ASSUMES CLIENT HAVE ONE CONNECTION TO ONE SERVER
* SERVERS MAY HAVE MANY CONECTIONS
**********************************************************************/
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <unistd.h>
#include <time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <linux/socket.h>
#include <netinet/tcp.h>
#include <netinet/in.h>
#include <netdb.h>
#include "inf.h"
#include "maTcp.h"
#include "maTcpLoc.h"
#include "includes.h"
/**************************** DEFINES ***********************************/
#define MAXPORTS 10
#define RDSIZ 8192
typedef struct sockaddr_in sock_t; // from: netinet/in.h
#define SET_NOBLOCK(fd) ioctl(fd,FIONBIO,&NoBlk)
#define RDBUFSIZ 8192
typedef unsigned long long ull;
/**************************** VARIABLES ***********************************/
pcb_t *Ports[MAXPORTS];
static int NoBlk = 1; // USED WHEN SET_NOBLOCK, CALLED
extern int h_errno;
/**************************** PROTOTYPES ***********************************/
static int ipAccept( ccb_t *cp );
static ccb_t *ipAddCcb( pcb_t *pp );
static iob_t *ipAddIob( iob_t **ipp, int len );
static pcb_t *ipAddPort( char *dev, int flg );
static int tcpAddr( ccb_t *cp, char *host, short port );
static ccb_t *ipConn( pcb_t *pp );
static int ipDconn( ccb_t *cp );
static int ipDoRsts( ccb_t *cp );
static int ipFreeCcb( ccb_t *cp );
static int ipFreeIob( iob_t **ip );
static int ipFreePcb( pcb_t *pp );
static int ipRdCplt( ccb_t *cp );
static int ipRdErr( ccb_t *cp, int rtn, int eno );
static int rdIrq();
static int tcpGetSd();
static int wtIrq();
/*F**********************************************************************
* DESC: OPEN IP CLIENT PORT
* RTRN: PORT HANDLE NBR, ELSE ERR
*F**********************************************************************/
int // "Host:Port" ("WxIfc.ary.loc:6100")
ipOpnClt( char *dev ) // FLG = IP_CLT
{ // CLIENT SHOULD GO AHEAD AND CONNECT TO SERVER
int sd, pHndl;
pcb_t *pp;
ccb_t *cp;
utTrc( 50,"Bgn, dev %s", dev );
if( (pp = ipAddPort( dev, IP_CLT )) <=0) // NEW PORT CTL BLK
return( utTrcErr("ipAddPort failed"));
pHndl = pp->pNdx;
pp->flags |= IP_CLT; // SET PCB's CLIENT FLAG
if( !(cp = ipConn( pp )))
return( utTrcErr("ipConn failed"));
utTrc( +50,"End OK, sd %d", sd );
return( pHndl );
}
/*F**********************************************************************
* DESC: OPEN SERVER
* RTRN: PORT HANDLE NBR, ELSE ERR
*F**********************************************************************/
int // "Host:Port" ("WxIfc.ary.loc:6100")
ipOpnSrv( char *dev ) // FLG = IP_SRV
{
int sd, pHndl, rtn;
char error[80];
pcb_t *pp;
ccb_t *cp;
utTrc( +50,"Bgn, dev %s", dev );
if( (pp = ipAddPort( dev, IP_SRV )) <=0 )
return( utTrcErr("ipAddPort failed"));
pHndl = pp->pNdx;
cp = ipAddCcb( pp ); // CREATE INITIAL CONN CTRL BLK
cp->sd = sd = tcpGetSd(); // GET A SOCKET
cp->pNdx = pp->pNdx;
cp->in = ipAddIob( &cp->in, RDSIZ ); // CREATE INITIAL IOB
utTrc( +20,"Host: %s, Port %d", pp->host, pp->hPort );
if( tcpAddr( cp, pp->host, pp->hPort ) != OK ) // ADDRESS SOCKET
return( utTrcErr("tcpAddr error"));
if( (rtn = bind( cp->sd, (struct sockaddr*)&cp->sock, cp->sockSiz)) <0)
return( utTrcErr( "[%s] bind error: %d", pp->host, errno), 0-errno);
if( listen( cp->sd, 8 ) < 0 ) // LISTEN FOR CONNECTIONS
return( utTrcErr("[%s] listen error", pp->host ));
SET_NOBLOCK( sd );
ioRegWat( sd, rdIrq, wtIrq, NULL, (void*)cp );
utTrc( +50,"End OK, sd %d", sd );
return( rtn );
}
/*F**********************************************************************
* DESC: CLOSE PORT, CLEAN UP
* RTRN:
*F**********************************************************************/
int
ipClose( int pHndl )
{
pcb_t *pp;
utTrc( 50, "Bgn");
if( !(pp = Ports[pHndl]))
return( utTrcErr("Bad Handle: [%d]", pHndl));
if( pp->cp )
ipFreeCcb( pp->cp );
ipFreePcb( pp );
utTrc( 50, "End");
return( OK );
}
/*F**********************************************************************
* DESC: Rcv data from host, 52us+ / char
* RTRN: LEN ELSE ERR
*F**********************************************************************/
int
ipRd( int pHndl, uchar *msg )
{
int rtn;
pcb_t *pp;
ccb_t *cp;
iob_t *ip;
utTrc( +50,"Bgn");
if( !(pp = Ports[pHndl])) // GET PORT CTRL BLK
return( utTrcErr("Bad Handle [%d]", pHndl));
cp = pp->cp;
if( !(ip = cp->in) ) // GET INP IOB PTR FROM CONN CTL BLK
ip = ipAddIob( &cp->in, RDSIZ );
if( pp->flags & IP_CLT )
ip->state =1; // PREVENT CLIENT FROM ACCEPTING CONNECTIONS
if( !(ip->flags & IP_CMPLT))
return( utTrc( 50,"Not Cmplt"),NOTFND );
utTrc( +50,"Read Complete: %d", ip->totCnt );
rtn = ip->totCnt - HDRSIZ;
ip->msg[rtn -1] =0;
strcpy( (char*)msg, ip->msg );
ipFreeIob( &cp->in );
utTrc( 50, "End: [%d], dLen:%d", pHndl, cp->dLen );
return( rtn );
}
/*F**********************************************************************
* DESC: INITIATE AND SEND DATA TO ANOTHER PROCESS
* RTRN: CUR CNT ELSE ERR
*F**********************************************************************/
int
ipWt( int pHndl, uchar *msg, int len )
{ // SEND DATA TO ANOTHER PROCESS
int rtn;
uchar *wtP, *ptr;
pcb_t *pp;
ccb_t *cp;
iob_t *ip;
utTrc( +50,"Bgn, len: %d", len);
if( !(pp = Ports[pHndl]))
return( utTrcErr("Bad Handle [%d]", pHndl));
if( !(cp = pp->cp))
cp = ipConn( pp );
ip = ipAddIob( &cp->out, HDRSIZ + len ); // GET OUTPUT BUFFER
if( (pp->flags & IP_CLT) || (pp->flags & IP_CONND) )
ip->state = 1;
ip->curCnt = 0; // CLEAR CURRENT READ COUNT
ip->totCnt = HDRSIZ + len;
memcpy( ip->msg, msg, len );
sprintf( ip->hdr, "%04d", len );
ioSetWatOut( cp->sd ); // ARM INTERRUPT, THUS START TRANSFER
while( !(ip->flags & IP_CMPLT) )
ioWait( 100 ); // WAIT FOR WT TO COMPLETE
rtn = ip->curCnt;
ipFreeIob( &cp->out );
utTrc( +52,"END OK, wrote:%d", rtn);
return( rtn );
}
/*F*********************************************************************
* DESC: SERVER ACCEPT CONNECTION
* RTRN: CUR CNT, ELSE ERR
*F*********************************************************************/
static int
ipAccept( ccb_t *cp )
{
int sd;
pcb_t *pp;
ccb_t *cp2;
iob_t *ip;
utTrc( 50, "Bgn");
pp = cp->pp;
if( !(pp->flags & IP_SRV) )
{ // ONLY SERVERS ACCEPT CONNECTIONS
utTrcErr( "Accept on Client?");
return( ipDconn( cp ));
}
if((sd = accept( cp->sd, (void*)&cp->sock, (socklen_t*)&cp->sockSiz))<0)
{
if( errno == EINVAL )
ipDconn( cp );
return( utTrcErr( "accept Error eno:%d", errno ));
}
utTrc( +50,"Sd:%d, %s", sd, cp->pp->host );
if( (cp2 = ipAddCcb( pp )) <=0 ) // CREATE NEW CONN CTL FOR NEW CKT
{
close( sd );
ipDconn( cp );
return( utTrcErr( "ipAddCcb Err") );
}
cp2->sd = sd;
SET_NOBLOCK( sd );
ip = ipAddIob( &cp2->in, RDSIZ );
ip->state =1;
pp->flags |= IP_CONND;
ioRegWat( sd, rdIrq, wtIrq, NULL, (void*)cp2 );
utTrc( +50,"End, Sd:%d OK", cp2->sd );
return( NOTFND );
}
/*F**********************************************************************
* DESC: CLOSE & RE-OPEN IP PORT
* RTRN:
*F**********************************************************************/
int
ipRstrt( int pHndl )
{
int hndl;
pcb_t *pp;
utTrc( 50, "Bgn");
if( !(pp = Ports[pHndl]) )
return( utTrcErr("Bad port handle [%d]", pHndl));
ipClose( pHndl );
if( pp->flags & IP_CLT )
hndl = ipOpnClt( pp->dev );
else
hndl = ipOpnSrv( pp->dev );
utTrc( 50, "End");
return( hndl );
}
// ***************** ALL STATIC FUNCS BEYOND THIS POINT *******************
/*F**********************************************************************
* DESC: READ INTRPT CALL-BACK rdIrq DOES ALL IN-BOUND XFER DATA WORK
* RTRN:
*F**********************************************************************/
static int // SHOULD READ HDR INTO ccb'S HDR1, THEN CREATE NEW IOB
rdIrq( ccb_t *cp ) // ipRd SHOULD FREE IOB AFTER SOPYING IT"S DATA
{
int rtn, rdCnt, siz;
uchar *rdp, hdr[16];;
iob_t *ip;
if( !(ip = cp->in))
ip = cp->in = ipAddIob( &cp->in, RDSIZ );
if( cp->pp->flags & IP_CLT )
ip->state = 1;
utTrc( +52,"Begin, sock: %d, State: %d", cp->sd, ip->state);
while( 1 )
{
switch( ip->state )
{
case 0: // UNCONNECTED
if( cp->pp->flags & IP_CONND )
{
ip->state = 1;
break;
}
if( cp->pp->flags & IP_SRV )
return( ipAccept( cp )); // ACCECPT NEW CONNECTION
utTrc( 40,"State:0, pp->flags: 0X%0x NOT SUPPOSED TO GET HERE!"
, cp->pp->flags);
ipDconn( cp );
break;
case 1: // BGN HDR RD
ip->totCnt = HDRSIZ;
ip->curCnt = 0;
ip->state++; // MOVE TO NEXT STATE
break;
case 2: // HDR RD CMPLT, BGN RD MSG
memcpy( hdr, ip->hdr, 4 ); // CPY XMITTED LEN
hdr[4] = 0; // MAKE SURE ITS A STR
siz = atoi( hdr ); // GET MSG LEN
if( siz > (RDSIZ - HDRSIZ))
return( utTrcErr("Msg too large: %d", siz), ipDconn(cp));
ip->totCnt += siz;
ip->curCnt = HDRSIZ; // SKIP HEADER
ip->state++; // MOVE TO NEXT STATE
break;
case 3: // RD MSG
if( ip->curCnt >= ip->totCnt )
return( ipRdCplt( cp )); // END OF MSG
break;
}
rdCnt = ip->totCnt - ip->curCnt;
rdp = &ip->hdr[ip->curCnt];
utTrc( +50,"Recv, sock: %d, rdCnt: %d, curCnt: %d"
, cp->sd, rdCnt, ip->curCnt );
if( (rtn = recv( cp->sd, rdp, rdCnt, 0 )) < 0 )
{
if( (rtn < 0) && (errno == EAGAIN))
continue;
return( ipRdErr( cp, rtn, errno ));// GO FIGURE OUT WHAT ERROR IS
}
utTrc( 50,"Recvd [%s]\n", ip->hdr );
ip->curCnt += rtn;
}
utTrc( +52,"BAD End");
return( OK );
}
/*F**********************************************************************
* DESC: WRITE INTERRUPT CALL-BACK wtIrq DOES ALL OUT_BOUND XFER DATA WORK
* RTRN:
*F**********************************************************************/
static int
wtIrq( ccb_t *cp )
{
int ret, wtCnt, eno;
char *ptr;
iob_t *ip;
ip = cp->out;
utTrc( +52,"Bgn, sock: %d", cp->sd );
wtCnt = ip->totCnt - ip->curCnt;
ptr = (char*)&ip->hdr[ip->curCnt];
if( (ret = send( cp->sd, ptr, wtCnt, 0 )) < 0 )
{
eno = errno;
ioClrWatOut( cp->sd );
return( utTrcErr("Write error, ret: %d, eno:%d", ret, eno));
}
if( ret > 0 )
ip->curCnt += ret;
if( ip->curCnt == ip->totCnt )
{
ioClrWatOut( cp->sd );
ip->flags |= IP_CMPLT;
utTrc( +52,"Write End, Len: %d", ip->curCnt );
return( OK );
}
utTrcErr( "Not Found");
return( NOTFND );
}
/*F*********************************************************************
* DESC:
* RTRN:
*F*********************************************************************/
static int
ipRdErr( ccb_t *cp, int rtn, int eno )
{ // SORT OUT WHAT KIND OF ERROR, AND WHAT TO DO ABOUT IT
utTrc( 50,"rtn:%d, eno:%d", rtn, eno );
if((rtn <0) && ((eno == EWOULDBLOCK) || (eno == ENOMEM) || (eno == EAGAIN)
|| (eno == EINTR)) )
return( utTrc( +50, "Sd:%d Blkd, rtn:%d", cp->sd, rtn), 0);
// if( eno == EAGAIN )
// return( 0 );
if( !rtn || (eno ==ECONNRESET) || (eno ==ECONNREFUSED)
|| (eno ==ENOTSOCK) || (eno ==EPIPE) || (eno ==ENOTCONN) || (eno ==EBADF)
|| (eno ==EINVAL))
return( utTrcErr("eno:%d, Cnt:%d", eno, rtn), ipDoRsts( cp ));
utTrc( 50,"Leaving");
return( ERR );
}
/*F*********************************************************************
* DESC:
* RTRN:
*F*********************************************************************/
static int
ipRdCplt( ccb_t *cp )
{
iob_t *ip;
utTrc( 50,"BGN");
ip = cp->in;
ip->flags |= IP_CMPLT;
cp->dLen = ip->curCnt;
utTrc( 40,"Rd Cmplt: tot:%d, dLen:%d", ip->totCnt, cp->dLen );
return( OK );
}
/*F*********************************************************************
* DESC: CONNECT
* RTRN:
*F*********************************************************************/
static ccb_t*
ipConn( pcb_t *pp )
{
int sd, rtn, eno, pHndl;
char errBuf[STRMAX];
ccb_t *cp;
utTrc( +50,"Bgn");
pp->cp = cp = ipAddCcb( pp ); // CREATE INITIAL CONN CTL BLK
cp->sd = sd = tcpGetSd(); // GET A SOCKET DESCRIPTOR
cp->pNdx = pp->pNdx;
utTrc( +50,"Host: %s, Port %d", pp->host, pp->hPort );
if( tcpAddr( cp, pp->host, pp->hPort ) != OK ) // SET SOCK ADDR
return( utTrcErr("tcpAdr Err"), NULL );
utTrc( +50,"Connecting Sd:%d", sd );
if( (rtn = connect( sd, (void*)&cp->sock, cp->sockSiz )) != 0)
{ // CONNECT FAILED
eno = errno;
strcpy( errBuf, pp->dev ); // SAVE PCB "host:port"
ipClose( pHndl ); // CLOSE PCB
if( (eno == ECONNREFUSED) )
return( utTrcErr( "Conn refused Host:%s", errBuf ), NULL);
return( utTrcErr( "connect errBuf %d", eno ), NULL);
}
pp->flags |= IP_CONND; // SHOW CLIENT AS CONNECTED
SET_NOBLOCK( sd );
ioRegWat( sd, rdIrq, wtIrq, NULL, (void*)cp );
utTrc( +50,"End OK, sd %d", sd );
return( cp );
}
/*F*********************************************************************
* DESC: DISCONNECT, FREE ccb
* RTRN:
*F*********************************************************************/
static int
ipDconn( ccb_t *cp )
{
int sd, flags;
pcb_t *pp;
ccb_t **cpp, *cp2;
sd = cp->sd;
utTrc( +50,"Bgn Sd:%d", sd );
pp = cp->pp;
for( cpp = &pp->cp; (cp2 = *cpp) && (cp2->sd != sd)
; cpp = &cp2->link); // FIND CP->SD IN PCB CHAIN
if( !cp2 )
return( utTrcErr("BAD ccb ptr for Sd:%d", sd));
*cpp = cp->link;
ioDregWat( sd );
close( sd ); // TELLS ANY CONNECTED HOST TO QUIT
if( cp->in )
ipFreeIob( &cp->in ); // FREE ALL MESSAGES IN INPUT QUEUE
if( cp->out )
ipFreeIob( &cp->out ); // FREE ALL MESSAGES IN OUTPUT QUEUE
ipFreeCcb( cp );
pp->flags &= !IP_CONND; // TURN CONNECTED FLAG OFF
utTrc( +50,"End Sd:%d", sd );
return( NOTFND );
}
/*F*********************************************************************
* DESC: ADD PORT CTRL BLOCK
* RTRN: PTR TO PCB ELSE NULL, ERR
*F*********************************************************************/
static pcb_t*
ipAddPort( char *dev, int flg )
{
int sd, ndx, rtn, sockSiz, eno;
char *sp, error[80];
pcb_t *pp;
ccb_t **cpp, *cp;
utTrc( +50,"Bgn, dev %s", dev );
for( ndx =0; (ndx < MAXPORTS) && Ports[ndx] ; ndx++ );// FND UNUSED PORT
pp = Ports[ndx] = calloc( 1, sizeof( pcb_t )); // ALLOC A NEW PCB
pp->pNdx = ndx; // SAVE PORTS[NDX]
pp->flags |= flg;
pp->dev = strdup( dev );
pp->host = strdup( dev );
pp->hdrLen = HDRSIZ;
sp = zotChr( pp->host, ':' ); // IP PORT NBR
pp->hPort = atoi( sp ); // CONVERT ASCII PORT TO INT
utTrc( 50, "End, P-%d, 0X%p", ndx, (void*)pp);
return( pp );
}
/*F*********************************************************************
* DESC: ADD CONNECTION CONTROL BLOCK
* RTRN: PTR TO CCB ELSE ERR AKA ipAddCcb
*F*********************************************************************/
static ccb_t*
ipAddCcb( pcb_t *pp )
{
ccb_t **cpp, *cp, *cp2;
utTrc( 50, "Bgn");
cp2 = pp->cp; // GET CURRENT CONN CTL BLK
if( !(cp = calloc( 1, sizeof( ccb_t ))))
return( utTrcErr("Ccb calloc failed"),(ccb_t*)ERR);
pp->cp = cp; // INSERT NEW CCB TO PP's CCB CHAIN
if( cp2 )
cp->link = cp2; // ADD ORIGINAL CONN CTL BLK TO NEW CCB's TAIL
cp->sockSiz = sizeof( sock_t );
cp->pNdx = pp->pNdx;
cp->pp = pp;
utTrc( 50, "End, 0X%p", (void*)cp );
return( cp );
}
/*F*********************************************************************
* DESC: MAKE I/O CNTRL BLCK, IPP POINTS TO CCB IN OR OUT CHAIN
* RTRN:
*F*********************************************************************/
static iob_t*
ipAddIob( iob_t **ipp, int len )
{
int siz;
ccb_t *cpp;
iob_t *ip, *ip1;
utTrc( 50, "Bgn");
siz = sizeof( iob_t ) + len + HDRSIZ;
if( !(ip = calloc( 1, siz )))
return( utTrcErr("iob calloc failed"), (iob_t*)ERR);
if( (ip1 = *ipp))
ip->link = ip1; // PUT NEW IOB IN FRONT OF QUEUE
*ipp = ip;
ip->siz = len; // SAVE EXPECTED MSG SIZE
utTrc( 50, "End, 0X%p", (void*)ip );
return( ip );
}
/*F*********************************************************************
* DESC: FREE PORT CTRL BLK
* RTRN:
*F*********************************************************************/
static int
ipFreePcb( pcb_t *pp )
{
int pHndl;
utTrc( 50, "Bgn");
pHndl = pp->pNdx;
free( pp->host );
free( pp->dev );
free( pp ); // FREE PCB
Ports[pHndl] = NULL;
utTrc( 50, "End");
return( OK );
}
/*F*********************************************************************
* DESC: FREE CONNECTION BLOCK
* RTRN:
*F*********************************************************************/
static int
ipFreeCcb( ccb_t *cp )
{
ccb_t *cp1, *cp2;
iob_t *ip1, *ip2;
utTrc( 50, "Bgn");
ioDregWat( cp->sd );
close( cp->sd );
cp->sd =0;
for( cp1 = cp; cp1 ; cp1 = cp2 )
{ // FREE ANY CONNECTIONS
cp2 = cp1->link;
while( cp1->in )
ipFreeIob( &cp1->in );
while( cp1->out )
ipFreeIob( &cp1->out );
free( cp1 );
}
utTrc( 50, "End");
return( OK );
}
/*F*********************************************************************
* DESC: FREE IO BLOCK ON FRONT OF CHAIN
* RTRN:
*F*********************************************************************/
static int
ipFreeIob( iob_t **ipp )
{
iob_t *ip, *ip1;
utTrc( 50, "Bgn");
ip = *ipp;
*ipp = ip->link;
free( ip );
utTrc( 50, "End");
return( OK );
}
/*F*********************************************************************
* DESC: FREE PORT CTRL BLK
* RTRN:
*F*********************************************************************/
static int
ipDoRsts( ccb_t *cp )
{
utTrc( 50,"Rst Sd: %d", cp->sd );
ipDconn( cp );
// if( pp->flags & IP_CLT )
// ipRecon( pp );
return( ERR );
}
/*F*********************************************************************
* DESC: Get a TCP socket.
* RTRN: Socket Descriptor (positive integer) else ERR.
*F*********************************************************************/
static int
tcpGetSd()
{
int sd, option;
utTrc( 50, "Bgn");
if(( sd = socket( AF_INET, SOCK_STREAM, 0 )) < 0 )
return( utTrcErr( "socket() error eno:%d", errno ));
option = RDBUFSIZ;
setsockopt( sd, SOL_SOCKET, SO_SNDBUF, (char*)&option, sizeof(option));
setsockopt( sd, SOL_SOCKET, SO_RCVBUF, (char*)&option, sizeof(option));
option = 1;
setsockopt( sd, SOL_SOCKET, SO_KEEPALIVE, (char*)&option, sizeof(option));
setsockopt( sd, SOL_SOCKET, SO_REUSEADDR, (char*)&option, sizeof(option));
setsockopt( sd, SOL_TCP, TCP_NODELAY, (char*)&option, sizeof(option));
utTrc( +50,"returning Sd:%d", sd );
return( sd );
}
/*F*********************************************************************
* DESC: Implements "makSock", Convert an io addr to TCP socket addr.
* RTRN: OK, else Err.
*F*********************************************************************/
static int
tcpAddr( ccb_t *cp, char *host, short port)
{
char tmp[STRMAX];
struct hostent *he; // from netdb.h
sock_t *sap;
utTrc( 50, "Bgn");
sap = (sock_t*)&cp->sock;
sap->sin_family = AF_INET;
sap->sin_port = htons( port );
strUcp( tmp, host );
if( !strcmp( host, "*" ) || !strcmp( tmp, "LOCALHOST" ) )
sap->sin_addr.s_addr = htonl( INADDR_LOOPBACK ); // FORCE LOOPBACK
else
{
if( !(he = gethostbyname( host )))
return( utTrcErr( "Can't address sock [%s], Err: %s"
, host, strerror( errno) ));
sap->sin_addr.s_addr = ((struct in_addr*)(he->h_addr))->s_addr;
} // from: netinet/in.h h_addr_list[0]
utTrc( 50, "End");
return( OK );
}
maTcp.h
/*H**********************************************************************
*
**********************************************************************/
#ifndef _MA_IP_H
#define _MA_IP_H
// ***************** PROTOTYPES **************************
int ipOpnClt( char *dev ); // OPEN CLIENT, RTN PORT HANDLE
int ipOpnSrv( char *dev ); // OPEN SERVER, RTN PORT HANDLE
int ipWt( int pHndl, uchar *buf, int len ); // RTN: CURCNT/ERR
int ipRd( int pHndl, uchar *buf ); // RTN: CURCNT/ERR
int ipClose( int pHndl ); // RTN: NEW PORT HANDLE
int ipRstrt( int pHndl ); // RTN: OK
#endif // _MA_IP_H
maTcpLoc.h
#ifndef _MA_IPLOC_H
#define _MA_IPLOC_H
// ============ FLAG BITS ============
#define IP_CLT 0X00000001
#define IP_SRV 0X00000002
#define IP_CONND 0X00000004
#define IP_INIT 0X00000008
#define IP_CMPLT 0X00000010
#define HDRSIZ 8
typedef struct sockaddr_in sock_t;
typedef struct iob { // INPUT/OUTPUT BUFFER
int state; // PORT STATE (SEE FLGS ABOVE)
int flags; // PORT STATE (SEE FLGS ABOVE)
int siz; // PORT STATE (SEE FLGS ABOVE)
int totCnt; // MSG TOT CNT
int curCnt; // MSG CURR CNT
struct ccb *cp;
struct iob *link;
char hdr[HDRSIZ]; // MESSAGE HDR
char msg[4]; // TRANSFERRED DATA
}iob_t;
typedef struct ccb { // CONNECTION CONTROL BLOCK
int flags; // CONECTION FLAGS
int pNdx; // Ports[] INDEX
int dLen; // RCV'D DATA LENGTH
int sd; // SOCKET DESCRIPTOR
int sockSiz; // SOCKET SIZE
sock_t sock; // SOCKET
iob_t *in; // IN_BOUND BUFFER QUEUE
iob_t *out; // OUT_BOUND BUFFER QUEUE
uchar hdr1[HDRSIZ]; // BUFF FOR READING MESSAGE HEADER (LEN)
struct pcb *pp; // PORT CONTROL BLOCK PTR
struct ccb *link; // CHAIN OF CCBs
}ccb_t;
typedef struct pcb { // PORT CONTORL BLOCK (BOTH LOCAL & REMOTE)
int pNdx; // PORTS[] NDX
int flags; // FLAGS, SEE ABOVE
int hdrLen; // HEADER LENGTH
short hPort; // HOST's PORT#
char *dev; // DEV "Host:Port"
char *host; // HOST NAME
ccb_t *cp; // CONNECTION CONTROL BLOCK
}pcb_t;
#endif // _MA_IPLOC_H
|
The Env server's resonse.
|