📄 udp4u.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 + -