///////////////////////////////////////////////////////////////////////////// // Rev 11/12/2003 // // // UDP.C // ----- // // // Sylvain MARECHAL - sylvain.marechal1@libertysurf.fr ///////////////////////////////////////////////////////////////////////////// /* ** Encapsulation des sockets bloquantes pour WIN32 et UNIX */ #include "winunix.h" #include "tcpudp.h" #include "udp.h" /*****************************************************/ /* Gestion des erreurs */ void UdpSetError( int err ) { TcpUdpSetError( err ); } int UdpGetError() { return TcpUdpGetError(); } /*****************************************************/ /*****************************************************/ /* Gestion du time out (-1:bloquant) */ void UdpSetTimeOut( int t ) { TcpUdpSetTimeOut(t); } int UdpGetTimeOut() { return TcpUdpGetTimeOut(); } /*****************************************************/ /*****************************************************/ SOCKET UdpCreate() { return TcpUdpCreate( SOCK_DGRAM ); } /*****************************************************/ BOOL UdpSetBroaCast( SOCKET hSocket ) { int optval = 1; if( setsockopt (hSocket,SOL_SOCKET, SO_BROADCAST, ( const char FAR * )&optval, sizeof(BOOL) ) == SOCKET_ERROR ) { UdpSetError( ERRNO ); return FALSE; } return TRUE; } /*****************************************************/ struct sockaddr UdpFormatAdress( char * host, u_short port ) { return TcpUdpFormatAdress( host, port ); } /*****************************************************/ int UdpBind( SOCKET hSocket, u_short portLocal ) { return TcpUdpBind( hSocket, portLocal ); } /*****************************************************/ int UdpSend( SOCKET hSocket, char * szBuffer, int cbBuffer, const struct sockaddr FAR * ptAddrTo ) { return UdpSendTo( hSocket, szBuffer, cbBuffer, ptAddrTo/*, FALSE*/ ); } /*****************************************************/ int UdpSendTo( SOCKET hSocket, char * szBuffer, int cbBuffer, const struct sockaddr FAR * ptAddrTo/*, BOOL fAck*/ ) { char szSendBuffer[TAILLE_BUFFER_SEND]; char * pszSend; int cbSend; BOOL fMalloc = FALSE; /* Reallocation de szSend si trop petit... On utilise pas des statics a cause du multithread Avec un peu de chance, si ( TAILLE_BUFFER_SEND > cbBuffer + TAILLE_ENTETE_UDP, on malloc jamais */ pszSend = szSendBuffer; if( cbBuffer + TAILLE_ENTETE_UDP > TAILLE_BUFFER_SEND ) { pszSend = ( char * )malloc( cbBuffer + TAILLE_ENTETE_UDP ); fMalloc = TRUE; } /* Creation entete + crc */ pszSend[0] = (unsigned char)( cbBuffer >> 8 ); /* / 256 <=> poids fort */ pszSend[1] = (unsigned char)( cbBuffer & 0xff) ; /* poids faible */ /*pszSend[2] = fAck;*/ pszSend[3] = pszSend[0] + pszSend[1] + pszSend[2]; /* Copie des donnees */ memcpy( pszSend + TAILLE_ENTETE_UDP, szBuffer, cbBuffer ); /* On envoie dans la nature */ if( ( cbSend = sendto ( hSocket, pszSend , cbBuffer + TAILLE_ENTETE_UDP, 0, ( const struct sockaddr FAR *)ptAddrTo, sizeof( struct sockaddr ) ) ) <= 0 ) { UdpSetError( ERRNO ); if( fMalloc ) free( pszSend ); return SOCKET_ERROR; } if( fMalloc ) free( pszSend ); return cbSend - TAILLE_ENTETE_UDP; } /*****************************************************/ int UdpRecv( SOCKET hSocket, char * szBuffer, int cbBuffer ) { /*BOOL fAck;*/ /* Un truc qui servira sans doute jamais ... */ int nTimeOut = 0; /* reception non bloquante */ return UdpRecvFrom( hSocket, szBuffer, cbBuffer, NULL, nTimeOut/*, &fAck*/ ); } /*****************************************************/ int UdpRecvFrom( SOCKET hSocket, char * szBuffer, int cbBuffer, struct sockaddr_in FAR * ptAddrFrom, int nTimeOut/*, BOOL * ptfAck*/ ) { int cbRecv, cbLenFrom; char szRecvBuffer[TAILLE_BUFFER_SEND]; char * pszRecv ; BOOL fMalloc = FALSE; /*struct*/ fd_set fd; struct timeval tv; /* Si -1, on va chercher le timeout defini par TcpGetTimeOut() */ nTimeOut = (nTimeOut == -1) ? UdpGetTimeOut() : nTimeOut; /* Gestion du time out . Si -1, mode bloquant */ tv.tv_sec = nTimeOut / 1000; tv.tv_usec = nTimeOut % 1000; FD_ZERO(&fd); #ifdef _WIN32 #pragma warning( disable : 4018 ) /* Desole ... */ #endif FD_SET(hSocket, &fd); #ifdef _WIN32 #pragma warning( default : 4018 ) #endif if(select( hSocket + 1, &fd, NULL, NULL, ( nTimeOut == -1 ? NULL : &tv) ) == SOCKET_ERROR ) { return SOCKET_ERROR; } /* Rien dans le buffer */ if (! FD_ISSET(hSocket, &fd)) { return 0; } /* Reallocation de szRecv si trop petit... On utilise pas des statics a cause du multithread Avec un peu de chance si ( TAILLE_BUFFER_SEND > cbBuffer + TAILLE_ENTETE_UDP, on malloc jamais */ pszRecv = szRecvBuffer; if( cbBuffer + TAILLE_ENTETE_UDP > TAILLE_BUFFER_SEND ) { pszRecv = ( char * )malloc( cbBuffer + TAILLE_ENTETE_UDP ); fMalloc = TRUE; } /* A t-on passe l'adresse ? */ if( ptAddrFrom != NULL ) cbLenFrom = sizeof( struct sockaddr ); /* On doit faire 1 seul recvfrom() (voir l'aide) */ if( ( cbRecv = recvfrom ( hSocket, pszRecv, cbBuffer + TAILLE_ENTETE_UDP, 0, ( struct sockaddr FAR *)ptAddrFrom, (ptAddrFrom == NULL ? NULL : &cbLenFrom) ) ) <= 0 ) { UdpSetError( ERRNO ); if( fMalloc ) free( pszRecv ); return cbRecv; } /* Test CRC */ if( pszRecv[3] != (pszRecv[0] + pszRecv[1] + pszRecv[2]) ) { UdpSetError( CRC_ERROR ); if( fMalloc ) free( pszRecv ); return SOCKET_ERROR; } /* Maj buffer */ memcpy( szBuffer, pszRecv + TAILLE_ENTETE_UDP, cbRecv - TAILLE_ENTETE_UDP); /* Maj Ack */ /**ptfAck = pszRecv[2];*/ if( fMalloc ) free( pszRecv ); return cbRecv - TAILLE_ENTETE_UDP; } /*****************************************************/ void UdpDestroy( SOCKET hSocket ) { TcpUdpDestroy( hSocket ); }