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

📄 udp4u.c

📁 ISO 8583 with c++ for financial transaction standard
💻 C
字号:
/*
 * Tcp4u v 3.30         Last Revision 11/12/1997  3.20
 *
 *===========================================================================
 *
 * Project: Tcp4u,      Library for tcp protocol
 * File:    udp4u.c
 * Purpose: main functions for udp protocol management
 *
 *===========================================================================
 *
 * This software is Copyright (c) 1996-1998 by Philippe Jounin
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 * 
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 * 
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA  02111-1307, USA.
 *
 *
 *  If you make modifications to this software that you feel
 *  increases it usefulness for the rest of the community, please
 *  email the changes, enhancements, bug fixes as well as any and
 *  all ideas to me. This software is going to be maintained and
 *  enhanced as deemed necessary by the community.
 *
 *
 *             Philippe Jounin (ph.jounin@computer.org)
 */

#include "build.h"

static char szWhat[] ="@(#)Udp4u by Ph. Jounin version 3.20";

/* ------------------------------------------------------------------------- */
/* Fonction de traduction Service -> port                                    */
/* ------------------------------------------------------------------------- */
unsigned short API4U Udp4uServiceToPort (LPCSTR szService)
{
unsigned short uPort = 0;
struct servent far *  lpServEnt;

  if (szService!=NULL)
  {
    Tcp4uLog (LOG4U_CALL, "getservbyname service %s", szService);
    lpServEnt = getservbyname (szService, "udp") ;
    if (lpServEnt==NULL)
       Tcp4uLog (LOG4U_ERROR, "getservbyname service %s", szService);
    else  uPort = ntohs (lpServEnt->s_port);
  }
return uPort;
} /* Udp4uServiceToPort */


/* ------------------------------------------------------------------------- */
/* initialisation UDP                                                        */
/* ------------------------------------------------------------------------- */
int API4U UdpInit (LPUDPSOCK far *pUdp, LPCSTR szHost, 
                   unsigned short uRemotePort, unsigned short uLocalPort)
{
int                   Rc;
SOCKET                UdpSock = INVALID_SOCKET;
struct  sockaddr_in   saSendAddr; /* structure identifiant le destinataire */
struct  sockaddr_in   saBindAddr; /* structure limitant les clients        */

  Tcp4uLog (LOG4U_PROC, "UdpInit, host %s", szHost);

  memset (& saBindAddr, 0, sizeof saBindAddr);
  memset (& saSendAddr, 0, sizeof saSendAddr); 
  /* --- 1. calcul de saSendAddr : RemoteService et szHost */
  saSendAddr.sin_family = AF_INET;
  saSendAddr.sin_port = htons (uRemotePort) ;
  if (szHost!=NULL)
  {
    saSendAddr.sin_addr = Tcp4uGetIPAddr (szHost);
    if (saSendAddr.sin_addr.s_addr==INADDR_NONE)   
    {
	     Tcp4uLog (LOG4U_ERROR, "UdpInit: host Unknown");
     	 return TCP4U_HOSTUNKNOWN;
    }
  } /* szHost is specified */
 
  /* --- autres champs de saBindAddr             */
  saBindAddr.sin_port = htons (uLocalPort);
  saBindAddr.sin_family = AF_INET;
  saBindAddr.sin_addr.s_addr = INADDR_ANY;

  /* --- Allocation de la socket */
  Tcp4uLog (LOG4U_CALL, "socket PF_INET SOCK_DGRAM");
  UdpSock = socket (PF_INET, SOCK_DGRAM, 0);
  if (UdpSock<0) 
  {
     Tcp4uLog (LOG4U_ERROR, "socket PF_INET SOCK_DGRAM");
     return TCP4U_NOMORESOCKET;
  }

  /* --- do a bind, thus all packets to be received will come on given port */
  Tcp4uLog (LOG4U_CALL, "bind to %s", inet_ntoa (saBindAddr.sin_addr));
  Rc = bind (UdpSock, (struct sockaddr far *) & saBindAddr, 
             sizeof(struct sockaddr));
  if (Rc<0)   
  { 
     Tcp4uLog (LOG4U_ERROR, "bind to %s", inet_ntoa (saBindAddr.sin_addr));
     CloseSocket (UdpSock);  
     return TCP4U_BINDERROR; 
  }

  /* --- Allocation de la structure */
  *pUdp = Calloc (sizeof (UDPSOCK), 1);
  if (*pUdp==NULL)  { CloseSocket (UdpSock);  return TCP4U_INSMEMORY; }
  (*pUdp)->UdpSock = UdpSock;
  (*pUdp)->saSendAddr = saSendAddr; 
  (*pUdp)->bSemiConnected = FALSE;  /* can receive data from any host */

   Tcp4uLog (LOG4U_EXIT, "UdpInit");
return TCP4U_SUCCESS;
} /* UdpInit */


/* ------------------------------------------------------------------------ */
/* UdpBind: Restrict socket to listen only from previous client             */
/* ------------------------------------------------------------------------ */
int API4U UdpBind (LPUDPSOCK pUdp, BOOL bFilter, int nMode)
{
   Tcp4uLog (LOG4U_PROC, "UdpBind Mode %d", nMode);

   if (bFilter)
   {
      switch (nMode)
      {
         /* le client ne peut recevoir que de la machine serveur           */
         /* le serveur que depuis la machine d'ou il a deja recu des infos */
         /* en mode serveur, l'adresse de destination devient l'adresse    */
         /* du dernier host.                                               */
         case UDP4U_CLIENT  :   pUdp->saFilter = pUdp->saSendAddr.sin_addr ; 
                                break;
         case UDP4U_SERVER  :   pUdp->saFilter = pUdp->saRecvAddr.sin_addr;
                                pUdp->saSendAddr = pUdp->saRecvAddr;
                                break;
         default            :   return TCP4U_ERROR;
      } /* selon mode */
   } /* si filtre positionne */
   /* filtre ou pas filtre */
   pUdp->bSemiConnected = bFilter;
   
   Tcp4uLog (LOG4U_EXIT, "UdpBind");
return  TCP4U_SUCCESS;
} /* UdpBind */



/* ------------------------------------------------------------------------- */
/* destructeur : UdpCleanup                                                  */
/* ------------------------------------------------------------------------- */
int API4U UdpCleanup (LPUDPSOCK Udp)
{
int Rc;
  Tcp4uLog (LOG4U_PROC, "UdpCleanup sock %d", Udp->UdpSock);

  Tcp4uLog (LOG4U_CALL, "closesocket sock %d", Udp->UdpSock);
  Rc = CloseSocket (Udp->UdpSock);
  if (Rc!=0)
  {
       Tcp4uLog (LOG4U_ERROR, "closesocket sock %d", Udp->UdpSock);
       return TCP4U_ERROR;
  }
  Free (Udp);

  Tcp4uLog (LOG4U_EXIT, "UdpCleanup");
return TCP4U_SUCCESS;
}  /* UdpCleanup */


/* ------------------------------------------------------------------------- */
/* Envoi d'une trame UDP                                                     */
/* ------------------------------------------------------------------------- */
int API4U UdpSend (LPUDPSOCK Udp, LPCSTR sData, int nDataSize,
                   BOOL   bHighPriority, HFILE hLogFile)
{
int Rc;
  Tcp4uLog (LOG4U_PROC, "UdpSend sock %d, %d bytes to be sent ", 
            Udp->UdpSock, nDataSize);
  Rc = InternalUdpSend (Udp, sData, nDataSize, bHighPriority, hLogFile);
  if (Rc==TCP4U_SUCCESS)   Tcp4uDump (sData, nDataSize, DUMP4U_SENT);
  Tcp4uLog (LOG4U_EXIT, "UdpSend");
return Rc;
} /* UdpSend */

int InternalUdpSend (LPUDPSOCK Udp,LPCSTR sData, int nDataSize,
                     BOOL   bHighPriority, HFILE hLogFile)
{
int Rc;

  Tcp4uLog (LOG4U_CALL, "sendto host %s sock %d, %d bytes to be sent ", 
            inet_ntoa (Udp->saSendAddr.sin_addr), 
            Udp->UdpSock, nDataSize);
  Rc = sendto (  Udp->UdpSock,    
                 sData, nDataSize, 
                 bHighPriority ? MSG_OOB : 0, 
                 (struct sockaddr far *) &Udp->saSendAddr, 
                 sizeof Udp->saSendAddr);
  /* --- Analyser la valeur retounee */
  if (Rc<0)
  {
        Tcp4uLog (LOG4U_ERROR, "sendto host %s", inet_ntoa (Udp->saSendAddr.sin_addr) );
        return TCP4U_ERROR;
  }
  if (hLogFile!=HFILE_ERROR)  Write (hLogFile, sData, Rc);

return Rc==nDataSize ? TCP4U_SUCCESS : TCP4U_OVERFLOW;
} /* InternalUdpSend */


/* ------------------------------------------------------------------------- */
/* La fonction reciproque : UdpRecv                                          */
/* ------------------------------------------------------------------------- */
int API4U UdpRecv (LPUDPSOCK pUdp,  LPSTR sData, int nDataSize, 
                  unsigned uTimeOut, HFILE hLogFile)
{
int            Rc;
  Tcp4uLog (LOG4U_PROC, "UdpRecv sock %d, buffer %d bytes", pUdp->UdpSock, nDataSize);
  Rc = InternalUdpRecv (pUdp, sData, nDataSize, uTimeOut, hLogFile);
  if (Rc>=TCP4U_SUCCESS)  Tcp4uDump (sData, Rc, DUMP4U_RCVD);
  Tcp4uLog (LOG4U_EXIT, "UdpRecv %d bytes received", Rc);
return Rc;
} /* UdpRecv */
  

int InternalUdpRecv (LPUDPSOCK pUdp,  LPSTR sData, int nDataSize, 
                     unsigned uTimeOut, HFILE hLogFile)
{
int            Rc;
struct timeval TO;
fd_set         ReadMask;                                      /* select mask */
int            Len = sizeof (struct sockaddr_in);

  if (pUdp->UdpSock==INVALID_SOCKET)  return TCP4U_ERROR;
  /* bug 1 :  Timeout kept in Loop, should be decremented                  */
  /* (can be done by the select function)                                  */
  /* bug 2 : some frames are read even if they do not concern this process */
  TO.tv_sec = (long) uTimeOut;                               /* secondes */
  TO.tv_usec = 0;                                       /* microsecondes */
  do
  {
     FD_ZERO (& ReadMask);                         /* mise a zero du masque */
     FD_SET (pUdp->UdpSock, & ReadMask);  /* Attente d'evenement en lecture */
     /* s+1 normally unused but better for a lot of bugged TCP Stacks */
     Tcp4uLog (LOG4U_CALL, "select Timeout %d", uTimeOut);
     Rc = select (  pUdp->UdpSock+1, 
                  & ReadMask, NULL, NULL, 
                    uTimeOut==0? NULL: &TO);
     if (Rc<0)
     {
          Tcp4uLog (LOG4U_ERROR, "select");
          return  IsCancelled() ? TCP4U_CANCELLED : TCP4U_ERROR;
     }
     if (Rc==0)
     {
          Tcp4uLog (LOG4U_ERROR, "select: Timeout");
          return  TCP4U_TIMEOUT;            /* timeout en reception */
     } 
   
     Tcp4uLog (LOG4U_CALL, "recvfrom host %s", inet_ntoa (pUdp->saRecvAddr.sin_addr));
     Rc = recvfrom (pUdp->UdpSock, sData, nDataSize, 0, 
                   (struct sockaddr far *) & pUdp->saRecvAddr, & Len);
     if (Rc<0)
     {
        Tcp4uLog (LOG4U_ERROR, "recvfrom");
        return TCP4U_ERROR;
     }
  }
  while (   pUdp->bSemiConnected  
         && memcmp (& pUdp->saRecvAddr.sin_addr, 
                    & pUdp->saFilter, 
                     sizeof  pUdp->saFilter) != 0);

  if (hLogFile!=HFILE_ERROR)  Write (hLogFile, sData, Rc);
return Rc;
} /* InternalUdpRecv */


⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -