📄 tcp4u.c
字号:
}
if (lpAddress!=NULL)
memcpy (lpAddress, & SockAddr.sin_addr.s_addr,
sizeof SockAddr.sin_addr.s_addr);
if (szStrName!=NULL && uNameSize > 0)
{
/* determiner par gethostbyaddr le nom de la station */
szStrName[0]=0; /* si erreur */
Tcp4uLog (LOG4U_DBCALL, "gethostbyaddr on host %s", inet_ntoa (SockAddr.sin_addr));
lpHostEnt = gethostbyaddr ((LPSTR) & SockAddr.sin_addr.s_addr, 4, PF_INET);
if (lpHostEnt!=NULL) Strcpyn (szStrName, lpHostEnt->h_name, uNameSize);
else Tcp4uLog (LOG4U_ERROR, "gethostbyaddr");
}
Tcp4uLog (LOG4U_EXIT, "TcpGetRemoteID");
return TCP4U_SUCCESS;
} /* TcpGetRemoteID */
/* ------------------------------------------------------------- */
/* TcpIsDataAvail: Retourne VRAI si des donnees sont disponibles */
/* ------------------------------------------------------------- */
BOOL API4U TcpIsDataAvail (SOCKET s)
{
unsigned long ulData;
int Rc;
Tcp4uLog (LOG4U_PROC, "TcpIsDataAvail on socket %d", s);
Tcp4uLog (LOG4U_CALL, "Ioctl FIONREAD on socket %d", s);
Rc = IoctlSocket (s, FIONREAD, & ulData);
Tcp4uLog (LOG4U_EXIT, "TcpIsDataAvail");
return Rc==0 && ulData>0;
} /* TcpIsDataAvail */
/* ------------------------------------------------------------- */
/* TcpIsOOBDataAvail: Retourne VRAI si des donnees Out Of Band */
/* sont disponibles */
/* ------------------------------------------------------------- */
BOOL API4U TcpIsOOBDataAvail (SOCKET s)
{
unsigned long ulData;
int Rc;
Tcp4uLog (LOG4U_PROC, "TcpIsOOBDataAvail on socket %d", s);
Rc = IoctlSocket (s, SIOCATMARK, & ulData);
Tcp4uLog (LOG4U_EXIT, "TcpIsOOBDataAvail");
return Rc==0 && ! ulData;
} /* TcpIsOOBDataAvail */
/* ******************************************************************* */
/* */
/* Partie II : Gestion d'un mini- protocole */
/* */
/* */
/* TcpPPSend - TcpPPRecv */
/* */
/* */
/* ******************************************************************* */
/* ------------------------------------------------------------ */
/* TcpPPRecv - Lecture d'une trame avec Timeout */
/* TcpPPRecv recoit uBufSize octets de donnies */
/* la fonction s'arrjte avant si la socket est fermie */
/* ou si un timeout arrive. */
/* - Retourne le nombre d'octets lus, */
/* TCP4U_SOCKETCLOSED si la socket a iti fermie */
/* TCP4U_ERROR sur une erreur de lecture */
/* TCP4U_TIMEOUT sur un TO */
/* TCP4U_BUFFERFREED si libiration des buffers */
/* - Remarque : Pour iviter que le buffer appelant soit */
/* libiri de manihre asynchrone, la fonction utilise */
/* ses propres buffers. */
/* ------------------------------------------------------------ */
int API4U TcpPPRecv (SOCKET s, LPSTR szBuf, unsigned uBufSize,
unsigned uTimeOut, BOOL bExact, HFILE hLogFile)
{
LPSTR p, q;
int Rc, nUpRc; /* Return Code of select and recv */
unsigned short nToBeReceived, nReceived;
Tcp4uLog (LOG4U_PROC, "TcpPPRecv on socket %d. Timeout %d, buffer %d bytes", s, uTimeOut, uBufSize);
if (s==INVALID_SOCKET) return TCP4U_ERROR;
Rc = TcpRecv (s, (LPSTR) & nToBeReceived, 2, uTimeOut, hLogFile);
if (Rc<TCP4U_SUCCESS) return Rc;
/* remise dans l'ordre PC */
nToBeReceived = ntohs (nToBeReceived);
/* Si longueur connue a l'avance, sinon ne pas depasser le buffer donne */
if (bExact && nToBeReceived!=uBufSize) return TCP4U_UNMATCHEDLENGTH;
if (uBufSize < nToBeReceived) return TCP4U_OVERFLOW;
if (nToBeReceived==0) return TCP4U_EMPTYBUFFER;
/* On elimine une des causes de crash: on lit dans un buffer qui n'existe plus */
q = p = Calloc (nToBeReceived, 1);
if (p==NULL) return TCP4U_INSMEMORY;
nReceived = 0;
nUpRc=0;
do /* On boucle tant qu'on a pas eu les nToBeReceived octets */
{
nUpRc = TcpRecv (s, q, nToBeReceived - nReceived, uTimeOut/4 + 1, hLogFile);
nReceived += (short) nUpRc;
q += nUpRc;
}
while (nUpRc>0 && nReceived<nToBeReceived);
/* Analyse du code de retour */
if (nUpRc >= TCP4U_SUCCESS)
{
if (IsBadWritePtr (szBuf, nToBeReceived)) nUpRc = TCP4U_BUFFERFREED;
else memcpy (szBuf, p, nUpRc=nToBeReceived);
}
Free (p);
Tcp4uLog (LOG4U_EXIT, "TcpPPRecv");
return nUpRc;
} /* TcpPPRecv */
/* -------------------------------------------------------------- */
/* TcpPPSend : Envoi de uBufSize octets vers le distant */
/* Retourne TCP4U_ERROR ou TCP4U_SUCCESS */
/* -------------------------------------------------------------- */
int API4U TcpPPSend (SOCKET s, LPCSTR szBuf, unsigned uBufSize, HFILE hLogFile)
{
int Rc;
unsigned short Total;
Tcp4uLog (LOG4U_PROC, "TcpPPSend on socket %d. %d bytes to send", s, uBufSize);
if (s==INVALID_SOCKET) return TCP4U_ERROR;
/* Envoi de la longueur de la trame sur 2 octets */
Total = htons ((unsigned short) uBufSize);
Rc = TcpSend (s, (void far *) & Total, 2, FALSE, hLogFile);
/* cas d'une sequence vide -> envoi de 0 OK: retour OK */
if (Rc>=TCP4U_SUCCESS && uBufSize>0)
/* maintenant on envoie la sequence (qui n'est pas vide) */
Rc = TcpSend (s, szBuf, uBufSize, FALSE, hLogFile);
Tcp4uLog (LOG4U_EXIT, "TcpPPSend");
return Rc;
} /* TcpPPSend */
/* ******************************************************************* */
/* */
/* Partie III : Lecture Jusqu'a ... */
/* */
/* */
/* ******************************************************************* */
/* ------------------------------------------------------------ */
/* TcpRecvUntilStr */
/* Recois des donnees jusqu'a */
/* - Une erreur */
/* - Une Fermeture de socket */
/* - un timeout */
/* - la reception de la chaine szStop */
/* - le remplissage du buffer */
/* Le Retour soit un code d'erreur, soit TCP4U_SUCCESS */
/* Si c'est TCP4U_OVERFLOW, uBufSize octes ont iti lus, mais */
/* la chaine szStop n'a pas iti trouvie */
/* Si c'est TCP4U_SOCKETCLOSED, le distant a ferme la connexion */
/* La chaine szStop n'est pas ajoutie au buffer */
/* lpBufSize contient le nombre d'octets lus */
/* NOTE: Cette fonction est incompatible avec La pile de Novell */
/* LAN Workplace */
/* ------------------------------------------------------------ */
/* redeclaration de tolower: MSCV2 semble avoir des problemes avec */
static char ToLower (char c)
{
return (c>='A' && c<='Z') ? c + ('a' -'A') : c;
} /* ToLower */
/* compare les chaines s1 et s2 sur nLength caracteres */
/* retourne TRUE si les deux chaines sont identiques */
static BOOL uMemcmp (LPSTR s1, LPSTR s2, int nLength, BOOL bCaseSensitive)
{
int Evan;
if (bCaseSensitive)
return memcmp (s1, s2, nLength)==0;
else
{
for (Evan=0 ; Evan<nLength && ToLower(s1[Evan])==ToLower(s2[Evan]) ; Evan++);
return Evan==nLength;
}
} /* uMemcmp */
/* Sous procedure : Recherche de la sous chaine s2 dans s1 */
/* Renvoie l'index de s1 auquel on peut trouver s2 */
/* ou -1 si s2 n'est pas incluse dans s1, dans */
/* ce cas, *nProx est le nombre d'octets de */
/* s2 contenu ` la fin de s1 */
static int FindPos (LPSTR s1, int ns1, LPSTR s2, int ns2, int *npProx, BOOL bCaseSensitive)
{
int Ark;
BOOL bNotFound;
if (*npProx!=0) /* on compare aussi si l'inclusion ne continue pas */
{
if (ns1<ns2-*npProx && uMemcmp (s1, & s2[*npProx], ns1, bCaseSensitive))
{ *npProx+=ns1 ; return -1; }
if (ns1>=ns2-*npProx && uMemcmp (s1, & s2[*npProx], ns2-*npProx, bCaseSensitive))
{ return 0; }
} /* traitement des antecedents */
for ( Ark=0, bNotFound=TRUE;
Ark<=ns1-ns2 && (bNotFound= ! uMemcmp (& s1[Ark], s2, ns2, bCaseSensitive)) ;
Ark++) ; /* recherche de s2 */
if (bNotFound)
{
for ( *npProx = min (ns1, ns2-1) ;
*npProx>0 && !uMemcmp (& s1[ns1-*npProx], s2, *npProx, bCaseSensitive);
(*npProx)-- );
}
return bNotFound ? -1 : Ark; /* si bNotFounf, *npProx est positionne */
} /* FindPos */
int API4U TcpRecvUntilStr (SOCKET s, LPSTR szBuf,unsigned far *lpBufSize,
LPSTR szStop, unsigned uStopSize, BOOL bCaseSensitive,
unsigned uTimeOut, HFILE hLogFile)
{
int Rc;
Tcp4uLog ( LOG4U_PROC,
"TcpRecvUntilStr on socket %d. Timeout %d, buffer %d bytes",
s, uTimeOut, *lpBufSize);
Rc = InternalTcpRecvUntilStr (s, szBuf, lpBufSize, szStop, uStopSize,
bCaseSensitive, uTimeOut, hLogFile);
if (Rc==TCP4U_SUCCESS) Tcp4uDump (szBuf, *lpBufSize, DUMP4U_RCVD);
if (Rc==TCP4U_OVERFLOW) Tcp4uDump (szBuf, *lpBufSize, "Overflow");
Tcp4uLog (LOG4U_EXIT, "TcpRecvUntilStr");
return Rc;
} /* TcpRecvUntilStr */
int InternalTcpRecvUntilStr (SOCKET s, LPSTR szBuf,unsigned far *lpBufSize,
LPSTR szStop, unsigned uStopSize, BOOL bCaseSensitive,
unsigned uTimeOut, HFILE hLogFile)
{
unsigned uNbRecus;
static int nProxy; /* Proxy sert si clef partagee sur 2 trames */
LPSTR pTest = NULL;
int Rc;
int Idx;
#define XX_RETURN(x,s) \
{ if (pTest!=NULL) Free(pTest); \
*lpBufSize=uNbRecus; \
Tcp4uLog (LOG4U_ERROR, IsCancelled() ? "call cancelled" : s); \
return IsCancelled() ? TCP4U_CANCELLED : x; }
if (s==INVALID_SOCKET || *lpBufSize==0) return TCP4U_ERROR;
/* On prend un buffer qui permet de lire la trame, */
/* la chaine de stop et qui soit toujours 0-terminee */
/* Le recv suivant est sur de ne pas bloquer, vu que */
/* le PEEK a rendu OK */
pTest = Calloc (*lpBufSize+uStopSize+1, 1);
if (pTest==NULL) return TCP4U_INSMEMORY;
uNbRecus = 0;
do
{
Rc = InternalTcpRecv (s, NULL, 0, uTimeOut, HFILE_ERROR);
/* ereur select */
if (Rc != TCP4U_SUCCESS) XX_RETURN (Rc, "Timeout");
/* Lecture en MSG_PEEK */
Tcp4uLog (LOG4U_CALL, "recv on socket %d. MSG_PEEK, buffer %d bytes",
s, *lpBufSize + uStopSize - uNbRecus);
Rc = recv (s, & pTest[uNbRecus], *lpBufSize+uStopSize-uNbRecus, MSG_PEEK);
if (Rc<=0) XX_RETURN (Rc, "TcpRecvUntilStr");
/* --- Maintenant on distingue 2 cas: */
/* Cas 1 : la clef est dans le buffer, */
Idx = FindPos (& pTest[uNbRecus], Rc, szStop, uStopSize,
& nProxy, bCaseSensitive);
if (Idx!=-1) /* la clef est disponible -> pas de probleme */
{
if ( IsBadWritePtr (& szBuf[uNbRecus], Idx) )
XX_RETURN (TCP4U_BUFFERFREED, "TcpRecvUntilStr: invalid pointer")
else
{
if (Idx!=0)
{
InternalTcpRecv (s, & szBuf[uNbRecus], Idx, 0, hLogFile);
uNbRecus += Idx;
}
else uNbRecus -= nProxy;
*lpBufSize = uNbRecus;
InternalTcpRecv (s, pTest, uStopSize - (Idx==0 ? nProxy:0),
0, hLogFile);
nProxy = 0; /* pour la prochaine recherche */
Free (pTest);
return TCP4U_SUCCESS;
}
} /* chaine trouvee */
else
/* Cas 2 : la clef n'est pas dans le buffer */
{int nToBeReceived = min (Rc, (signed) (*lpBufSize-uNbRecus));
if (IsBadWritePtr (& szBuf[uNbRecus], nToBeReceived) )
{
Free (pTest);
Tcp4uLog (LOG4U_ERROR, "TcpRecvUntilStr: invalid pointer");
return TCP4U_BUFFERFREED;
}
else
{
InternalTcpRecv (s, & szBuf[uNbRecus], nToBeReceived , 0, hLogFile);
uNbRecus += nToBeReceived;
}
} /* chaine pas trouvee */
}
while (uNbRecus<*lpBufSize);
Free (pTest);
*lpBufSize = uNbRecus;
#undef XX_RETURN
return TCP4U_OVERFLOW;
} /* InternalTcpRecvUntilStr */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -