winpipe.c

00001 /*
00002   Copyright (c) Fabasoft R&D Software GmbH & Co KG, 2003
00003   oss@fabasoft.com
00004   Author: Bernhard Penz <bernhard.penz@fabasoft.com>
00005 
00006   Redistribution and use in source and binary forms, with or without
00007   modification, are permitted provided that the following conditions are met:
00008 
00009   *  Redistributions of source code must retain the above copyright notice,
00010      this list of conditions and the following disclaimer.
00011 
00012   *  Redistributions in binary form must reproduce the above copyright
00013      notice, this list of conditions and the following disclaimer in the
00014      documentation and/or other materials provided with the distribution.
00015 
00016   *  The name of Fabasoft R&D Software GmbH & Co KG or any of its subsidiaries, 
00017      brand or product names may not be used to endorse or promote products 
00018      derived from this software without specific prior written permission.
00019 
00020   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER ``AS IS'' AND ANY
00021   EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00022   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
00023   PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
00024   LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00025   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00026   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
00027   BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
00028   WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
00029   OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
00030   IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00031 */
00032 
00033 #ifdef WIN32
00034 
00035 #include <io.h>
00036 #include <winsock.h>
00037 
00038 static int InitUPDSocket(SOCKET *sock, struct sockaddr_in *socketaddress)
00039 {
00040         *sock = 0;
00041         memset(socketaddress, 0, sizeof(struct sockaddr_in));
00042 
00043         if( (*sock = socket(AF_INET, SOCK_DGRAM, 0)) == SOCKET_ERROR)
00044         {
00045                 return -1;
00046         }
00047         socketaddress->sin_family = AF_INET;
00048         socketaddress->sin_addr.S_un.S_addr = htonl(INADDR_LOOPBACK);
00049         socketaddress->sin_port = 0;
00050 
00051         if(bind(*sock, (struct sockaddr *) socketaddress, sizeof(struct sockaddr)) == SOCKET_ERROR)
00052         {
00053                 return -1;
00054         }
00055 
00056         return 0;
00057 }
00058 
00059 static int ConnectUDPSocket(SOCKET *sock, struct sockaddr_in *socketaddress, SOCKET *remotesocket)
00060 {
00061         int size = sizeof(struct sockaddr);
00062         if (getsockname(*sock, (struct sockaddr *) socketaddress, &size) == SOCKET_ERROR)
00063         {
00064                 return -1;
00065         }
00066 
00067         if(size != sizeof(struct sockaddr))
00068         {
00069                 return -1;
00070         }
00071 
00072         if (connect(*remotesocket, (struct sockaddr *) socketaddress, sizeof(struct sockaddr)) == SOCKET_ERROR)
00073         {
00074                 return -1;
00075         }
00076 
00077         return 0;
00078 }
00079 
00080 static int TestUDPSend(SOCKET *sock, struct sockaddr_in *socketaddress)
00081 {
00082         unsigned short port = socketaddress->sin_port;
00083         int size = sizeof(struct sockaddr);
00084 
00085         int bytessent = send(*sock, (char *) &port, sizeof(port), 0);
00086         if(bytessent != sizeof(port))
00087         {
00088                 return -1;
00089         }
00090 
00091         return 0;
00092 }
00093 
00094 static int TestUDPReceive(SOCKET *sock, SOCKET *remotesocket, struct sockaddr_in *remotesocketaddress)
00095 {
00096         struct sockaddr_in recvfromaddress;
00097         unsigned short readbuffer[2];
00098         int size = sizeof(struct sockaddr);
00099 
00100         int bytesreceived = recvfrom(*sock,(char *) &readbuffer, sizeof(readbuffer), 0, (struct sockaddr *) &recvfromaddress, &size) ;
00101         if(bytesreceived != sizeof(unsigned short) || size != sizeof(struct sockaddr) || readbuffer[0] != (unsigned short) remotesocketaddress->sin_port || recvfromaddress.sin_family != remotesocketaddress->sin_family || recvfromaddress.sin_addr.S_un.S_addr != remotesocketaddress->sin_addr.S_un.S_addr || recvfromaddress.sin_port != remotesocketaddress->sin_port)
00102         {
00103                 return -1;
00104         }
00105 
00106         return 0;
00107 }
00108 
00109 static void CloseUDPSocketPair(SOCKET *socketpair)
00110 {
00111         int i = WSAGetLastError();
00112 
00113         if(socketpair[0] != INVALID_SOCKET)
00114         {
00115                 closesocket(socketpair[0]);
00116         }
00117         if(socketpair[1] != INVALID_SOCKET)
00118         {
00119                 closesocket(socketpair[1]);
00120         }
00121 }
00122 
00123 /*
00124         Windows unnamed pipe emulation, used to enable select()
00125         on a Windows machine for the CALLBACK (pipe-based) transport domain.
00126 */
00127 int create_winpipe_transport(int *pipefds)
00128 {
00129         SOCKET socketpair[2];
00130         struct sockaddr_in socketaddress[2];
00131 
00132         struct timeval waittime = {0, 200000};
00133         fd_set readset;
00134 
00135         if (InitUPDSocket(&socketpair[0], &socketaddress[0]))
00136         {
00137                 CloseUDPSocketPair(socketpair);
00138                 return -1;
00139         }
00140         if (InitUPDSocket(&socketpair[1], &socketaddress[1]))
00141         {
00142                 CloseUDPSocketPair(socketpair);
00143                 return -1;
00144         }
00145 
00146         /*
00147                 I have two UDP sockets - now lets connect them to each other.
00148         */
00149 
00150         if (ConnectUDPSocket(&socketpair[0], &socketaddress[0], &socketpair[1]))
00151         {
00152                 CloseUDPSocketPair(socketpair);
00153                 return -1;
00154         }
00155         if(ConnectUDPSocket(&socketpair[1], &socketaddress[1], &socketpair[0]))
00156         {
00157                 CloseUDPSocketPair(socketpair);
00158                 return -1;
00159         }
00160 
00161         /*
00162                 The two sockets are connected to each other, now lets test the connection
00163                 by sending the own port number.
00164         */
00165         if(TestUDPSend(&socketpair[0], &socketaddress[0]))
00166         {
00167                 CloseUDPSocketPair(socketpair);
00168                 return -1;
00169         }
00170         if(TestUDPSend(&socketpair[1], &socketaddress[1]))
00171         {
00172                 CloseUDPSocketPair(socketpair);
00173                 return -1;
00174         }
00175 
00176         /*
00177                 Port numbers sent, now lets select() on the socketpair and check that 
00178                 both messages got through
00179         */
00180         FD_ZERO(&readset);
00181         FD_SET(socketpair[0], &readset);
00182         FD_SET(socketpair[1], &readset);
00183 
00184         /*
00185                 For some unknown reason the timeout setting in the select call does not have
00186                 the desired effect, and for yet another unknown reason a Sleep(1) solves this
00187                 problem.
00188         */
00189         Sleep(1);
00190         if(select(0, &readset, NULL, NULL, &waittime) != 2 || !FD_ISSET(socketpair[0], &readset) || !FD_ISSET(socketpair[1], &readset))
00191         {
00192                 CloseUDPSocketPair(socketpair);
00193                 return -1;
00194         }
00195 
00196         /*
00197                 Check if the packets I receive were really sent by me, and nobody else
00198                 tried to sneak.
00199         */
00200     if(TestUDPReceive(&socketpair[0], &socketpair[1], &socketaddress[1]))
00201         {
00202                 CloseUDPSocketPair(socketpair);
00203                 return -1;
00204         }
00205         if(TestUDPReceive(&socketpair[1], &socketpair[0], &socketaddress[0]))
00206         {
00207                 CloseUDPSocketPair(socketpair);
00208                 return -1;
00209         }
00210 
00211         /*
00212                 All sanity checks passed, I can return a "UDP pipe"
00213         */
00214         pipefds[0] = (int) socketpair[0];
00215         pipefds[1] = (int) socketpair[1];
00216 
00217         return 0;
00218 }
00219 
00220 #endif /* WIN32 */
00221 

net-snmpに対してSat Sep 5 13:14:28 2009に生成されました。  doxygen 1.4.7