367 lines
6.8 KiB
C++
367 lines
6.8 KiB
C++
//
|
|
// $Id$
|
|
//
|
|
// verify connection state prior to doing anything in this file
|
|
//
|
|
//
|
|
// $Log$
|
|
// Revision 1.6 1996/11/02 00:54:46 jhill
|
|
// many improvements
|
|
//
|
|
// Revision 1.5 1996/09/16 18:25:16 jhill
|
|
// vxWorks port changes
|
|
//
|
|
// Revision 1.4 1996/07/24 22:03:36 jhill
|
|
// fixed net proto for gnu compiler
|
|
//
|
|
// Revision 1.3 1996/07/09 22:55:22 jhill
|
|
// added cast
|
|
//
|
|
// Revision 1.2 1996/06/21 02:18:11 jhill
|
|
// SOLARIS port
|
|
//
|
|
// Revision 1.1.1.1 1996/06/20 00:28:19 jhill
|
|
// ca server installation
|
|
//
|
|
//
|
|
|
|
#include <server.h>
|
|
|
|
|
|
//
|
|
// casStreamIO::casStreamIO()
|
|
//
|
|
casStreamIO::casStreamIO(caServerI &cas, const ioArgsToNewStreamIO &args) :
|
|
casStrmClient(cas),
|
|
sockState(casOffLine), sock(args.sock), addr(args.addr),
|
|
blockingFlag(xIsBlocking)
|
|
{
|
|
assert (sock>=0);
|
|
}
|
|
|
|
|
|
//
|
|
// casStreamIO::init()
|
|
//
|
|
caStatus casStreamIO::init()
|
|
{
|
|
int yes = TRUE;
|
|
int status;
|
|
|
|
/*
|
|
* see TCP(4P) this seems to make unsollicited single events much
|
|
* faster. I take care of queue up as load increases.
|
|
*/
|
|
status = setsockopt(
|
|
this->sock,
|
|
IPPROTO_TCP,
|
|
TCP_NODELAY,
|
|
(char *)&yes,
|
|
sizeof(yes));
|
|
if (status<0) {
|
|
ca_printf(
|
|
"CAS: %s TCP_NODELAY option set failed %s\n",
|
|
__FILE__, strerror(SOCKERRNO));
|
|
return S_cas_internal;
|
|
}
|
|
|
|
/*
|
|
* turn on KEEPALIVE so if the client crashes
|
|
* this task will find out and exit
|
|
*/
|
|
status = setsockopt(
|
|
sock,
|
|
SOL_SOCKET,
|
|
SO_KEEPALIVE,
|
|
(char *)&yes,
|
|
sizeof(yes));
|
|
if (status<0) {
|
|
ca_printf(
|
|
"CAS: %s SO_KEEPALIVE option set failed %s\n",
|
|
__FILE__, strerror(SOCKERRNO));
|
|
return S_cas_internal;
|
|
}
|
|
#ifdef MATCHING_BUFFER_SIZES
|
|
int i;
|
|
|
|
/*
|
|
* set TCP buffer sizes to be synergistic
|
|
* with CA internal buffering
|
|
*/
|
|
i = MAX_MSG_SIZE;
|
|
status = setsockopt(
|
|
sock,
|
|
SOL_SOCKET,
|
|
SO_SNDBUF,
|
|
(char *)&i,
|
|
sizeof(i));
|
|
if(status < 0){
|
|
ca_printf("CAS: SO_SNDBUF set failed\n");
|
|
return S_cas_internal;
|
|
}
|
|
i = MAX_MSG_SIZE;
|
|
status = setsockopt(
|
|
sock,
|
|
SOL_SOCKET,
|
|
SO_RCVBUF,
|
|
(char *)&i,
|
|
sizeof(i));
|
|
if(status < 0){
|
|
ca_printf("CAS: SO_RCVBUF set failed\n");
|
|
return S_cas_internal;
|
|
}
|
|
#endif
|
|
this->sockState = casOnLine;
|
|
|
|
return this->casStrmClient::init();
|
|
}
|
|
|
|
|
|
//
|
|
// casStreamIO::~casStreamIO()
|
|
//
|
|
casStreamIO::~casStreamIO()
|
|
{
|
|
if (sock>=0) {
|
|
close(this->sock);
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// casStreamIO::osdSend()
|
|
//
|
|
xSendStatus casStreamIO::osdSend(const char *pInBuf, bufSizeT nBytesReq,
|
|
bufSizeT &nBytesActual)
|
|
{
|
|
int status;
|
|
|
|
if (this->sockState!=casOnLine) {
|
|
return xSendDisconnect;
|
|
}
|
|
|
|
if (nBytesReq<=0u) {
|
|
nBytesActual = 0u;
|
|
return xSendOK;
|
|
}
|
|
|
|
status = send (
|
|
this->sock,
|
|
(char *) pInBuf,
|
|
nBytesReq,
|
|
0);
|
|
if (status == 0) {
|
|
this->sockState = casOffLine;
|
|
return xSendDisconnect;
|
|
}
|
|
else if (status<0) {
|
|
int anerrno = SOCKERRNO;
|
|
|
|
if (anerrno != EWOULDBLOCK) {
|
|
this->sockState = casOffLine;
|
|
}
|
|
nBytesActual = 0u;
|
|
return xSendOK;
|
|
}
|
|
nBytesActual = (bufSizeT) status;
|
|
return xSendOK;
|
|
}
|
|
|
|
|
|
//
|
|
// casStreamIO::osdRecv()
|
|
//
|
|
xRecvStatus casStreamIO::osdRecv(char *pInBuf, bufSizeT nBytes,
|
|
bufSizeT &nBytesActual)
|
|
{
|
|
int nchars;
|
|
|
|
if (this->sockState!= casOnLine) {
|
|
return xRecvDisconnect;
|
|
}
|
|
|
|
nchars = recv(this->sock, pInBuf, nBytes, 0);
|
|
if (nchars==0) {
|
|
this->sockState = casOffLine;
|
|
return xRecvDisconnect;
|
|
}
|
|
else if (nchars<0) {
|
|
char buf[64];
|
|
|
|
/*
|
|
* normal conn lost conditions
|
|
*/
|
|
switch(SOCKERRNO){
|
|
case EWOULDBLOCK:
|
|
nBytesActual = 0u;
|
|
return xRecvOK;
|
|
|
|
case ECONNABORTED:
|
|
case ECONNRESET:
|
|
case ETIMEDOUT:
|
|
break;
|
|
|
|
default:
|
|
ipAddrToA(&this->addr.in, buf, sizeof(buf));
|
|
ca_printf(
|
|
"CAS: client %s disconnected because \"%s\"\n",
|
|
buf, strerror(SOCKERRNO));
|
|
break;
|
|
}
|
|
this->sockState = casOffLine;
|
|
return xRecvDisconnect;
|
|
}
|
|
nBytesActual = (bufSizeT) nchars;
|
|
return xRecvOK;
|
|
}
|
|
|
|
|
|
//
|
|
// casStreamIO::show()
|
|
//
|
|
void casStreamIO::osdShow (unsigned level) const
|
|
{
|
|
printf ("casStreamIO at %x\n", (unsigned) this);
|
|
if (level>1u) {
|
|
char buf[64];
|
|
ipAddrToA(&this->addr.in, buf, sizeof(buf));
|
|
printf (
|
|
"client=%s, port=%x\n",
|
|
buf, ntohs(this->addr.in.sin_port));
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// casStreamIO::xSsetNonBlocking()
|
|
//
|
|
void casStreamIO::xSetNonBlocking()
|
|
{
|
|
int status;
|
|
int yes = TRUE;
|
|
|
|
if (this->sockState!=casOnLine) {
|
|
return;
|
|
}
|
|
|
|
status = socket_ioctl(this->sock, FIONBIO, &yes);
|
|
if (status>=0) {
|
|
this->blockingFlag = xIsntBlocking;
|
|
}
|
|
else {
|
|
ca_printf("%s:CAS: TCP non blocking IO set fail because \"%s\"\n",
|
|
__FILE__, strerror(SOCKERRNO));
|
|
this->sockState = casOffLine;
|
|
}
|
|
}
|
|
|
|
//
|
|
// casStreamIO::blockingState()
|
|
//
|
|
xBlockingStatus casStreamIO::blockingState() const
|
|
{
|
|
return this->blockingFlag;
|
|
}
|
|
|
|
|
|
//
|
|
// casStreamIO::incommingBytesPresent()
|
|
//
|
|
bufSizeT casStreamIO::incommingBytesPresent() const
|
|
{
|
|
int status;
|
|
int nchars;
|
|
|
|
status = socket_ioctl(this->sock, FIONREAD, &nchars);
|
|
if (status<0) {
|
|
char buf[64];
|
|
|
|
/*
|
|
* normal conn lost conditions
|
|
*/
|
|
switch(SOCKERRNO){
|
|
case ECONNABORTED:
|
|
case ECONNRESET:
|
|
case ETIMEDOUT:
|
|
break;
|
|
|
|
default:
|
|
ipAddrToA(&this->addr.in, buf, sizeof(buf));
|
|
ca_printf(
|
|
"CAS: FIONREAD for %s failed because \"%s\"\n",
|
|
buf, strerror(SOCKERRNO));
|
|
}
|
|
return 0u;
|
|
}
|
|
else if (nchars<0) {
|
|
return 0u;
|
|
}
|
|
else {
|
|
return (bufSizeT) nchars;
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// casStreamIO::clientHostName()
|
|
//
|
|
void casStreamIO::clientHostName (char *pInBuf, unsigned bufSizeIn) const
|
|
{
|
|
ipAddrToA (&this->addr.in, pInBuf, bufSizeIn);
|
|
}
|
|
|
|
//
|
|
// casStreamIO:::optimumBufferSize()
|
|
//
|
|
bufSizeT casStreamIO::optimumBufferSize ()
|
|
{
|
|
|
|
#if 0
|
|
int n;
|
|
int size;
|
|
int status;
|
|
|
|
if (this->sockState!=casOnLine) {
|
|
return MAX_TCP;
|
|
}
|
|
|
|
/* fetch the TCP send buffer size */
|
|
n = sizeof(size);
|
|
status = getsockopt(
|
|
this->sock,
|
|
SOL_SOCKET,
|
|
SO_SNDBUF,
|
|
(char *)&size,
|
|
&n);
|
|
if(status < 0 || n != sizeof(size)){
|
|
size = 0x400;
|
|
}
|
|
|
|
if (size<=0) {
|
|
size = 0x400;
|
|
}
|
|
printf("the tcp buf size is %d\n", size);
|
|
return (bufSizeT) size;
|
|
#else
|
|
// this needs to be MAX_TCP (until we fix the array problem)
|
|
return (bufSizeT) MAX_TCP;
|
|
#endif
|
|
}
|
|
|
|
//
|
|
// casStreamIO::getFD()
|
|
//
|
|
int casStreamIO::getFD() const
|
|
{
|
|
return this->sock;
|
|
}
|
|
|
|
//
|
|
// casStreamIO::state()
|
|
//
|
|
casIOState casStreamIO::state() const
|
|
{
|
|
return this->sockState;
|
|
}
|
|
|