⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tcp4u.c

📁 ISO 8583 with c++ for financial transaction standard
💻 C
📖 第 1 页 / 共 3 页
字号:
   }
   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 + -