ezSockets.cpp

Go to the documentation of this file.
00001 /*******************************************************************\
00002 | ezsockets.cpp: EzSockets Class Source                             |
00003 |   Designed by Josh Allen, Charles Lohr and Adam Lowman.           |
00004 |   Socket programming methods based on Charles Lohr's EZW progam.  |
00005 |   Modified by Charles Lohr for use with Windows-Based OSes.       |
00006 |   UDP/NON-TCP Support by Adam Lowman.                             |
00007 |                                                                   |
00008 |   Primary Editor: Charles Lohr                                    |
00009 \*******************************************************************/
00010 
00011 #include "ezSockets.h"
00012 
00013 #if defined(_MSC_VER) && !defined(_XBOX) // We need the WinSock32 Library on Windows
00014 #pragma comment(lib,"wsock32.lib")
00015 #elif !defined(__MINGW32__) && !defined(_XBOX)
00016 #include <sys/types.h>
00017 #include <sys/socket.h>
00018 #include <unistd.h>
00019 #include <arpa/inet.h>
00020 #include <netdb.h>
00021 #endif
00022 
00023 #if !defined(SOCKET_ERROR)
00024 #define SOCKET_ERROR -1
00025 #endif
00026 
00027 //There are cases where 0 isn't a proper socket
00028 #if !defined(SOCKET_NONE)
00029 #define SOCKET_NONE 0
00030 #endif
00031 
00032 #if !defined(INVALID_SOCKET)
00033 #define INVALID_SOCKET -1
00034 #endif
00035 
00036 #if defined(WIN32)
00037 typedef int socklen_t;
00038 #endif
00039 
00040 int iPackets = 0;
00041 #include <iostream>
00042 ezSocketsPacket::ezSocketsPacket()
00043 {
00044     Data = NULL;
00045     Next = NULL;
00046     iPackets++;
00047     Port = 0;
00048     ClearPacket();
00049 }
00050 
00051 ezSocketsPacket::~ezSocketsPacket()
00052 {
00053     iPackets--;
00054     if ( Data )
00055         free( Data );
00056 }
00057 
00058 void ezSocketsPacket::CopyPacket( ezSocketsPacket & pPacketToCopy )
00059 {
00060     Size = pPacketToCopy.Size;
00061     if ( Data )
00062         delete Data;
00063     Data = (char*)malloc( Size );
00064     memcpy( Data, pPacketToCopy.Data, Size );
00065     Position = 0;
00066     Next = NULL;
00067 }
00068 
00069 void ezSocketsPacket::DestroyTree()
00070 {
00071     if ( Next ) 
00072     {
00073         Next->DestroyTree();
00074         delete Next;
00075         Next = NULL;
00076     }
00077     if ( Data )
00078     {
00079         delete Data;
00080         Data = NULL;
00081     }
00082 }
00083 
00084 void ezSocketsPacket::ClearPacket()
00085 {
00086     if ( Data )
00087         free( Data );
00088     Data = NULL;
00089     Position = 0;
00090     Size = 0;
00091 }
00092 
00093 void ezSocketsPacket::SetupPacket( unsigned int iSize )
00094 {
00095     if ( Data )
00096         free( Data );
00097     Data = (char*)malloc( iSize );
00098     Position = 0;
00099     Size = iSize;
00100 }
00101 
00102 unsigned char   ezSocketsPacket::Read1()
00103 {
00104     if ( Position < Size )
00105         return Data[Position++];
00106     else
00107         return 0;
00108 }
00109 
00110 unsigned short  ezSocketsPacket::Read2()
00111 {
00112     if ( Position + 1 < Size )
00113         return ntohs( *((unsigned short*)&(Data[(Position+=2)-2])) );
00114     else
00115         return 0;
00116 }
00117 
00118 unsigned long   ezSocketsPacket::Read4()
00119 {
00120     if ( Position + 3 < Size )
00121         return ntohl( *((unsigned long*)&(Data[(Position+=4)-4])) );
00122     else
00123         return 0;
00124 }
00125 
00126 MString         ezSocketsPacket::ReadNT()
00127 {
00128     if ( Position >= Size )
00129         return MString("");
00130 
00131     char * base = &Data[Position];
00132 
00133     while ( Data[Position++] != '\0' );
00134 
00135     return MString(base);
00136 }
00137 
00138 void ezSocketsPacket::Write1( unsigned char Info )
00139 {
00140     Grow( Position + 1 );
00141     Data[Position++] = Info;
00142 }
00143 
00144 void ezSocketsPacket::Write2( unsigned short Info )
00145 {
00146     Grow( Position + 2 );
00147     *((short*)(&Data[Position])) = htons(Info);
00148     Position+=2;
00149 }
00150 
00151 void ezSocketsPacket::Write4( unsigned long Info )
00152 {
00153     Grow( Position + 4 );
00154     *((unsigned long*)(&Data[Position])) = htonl(Info);
00155     Position += 4;
00156 }
00157 
00158 void ezSocketsPacket::WriteNT( const MString& Info )
00159 {
00160     Grow( Position + Info.length() + 1 );
00161     memcpy( &Data[Position], Info.c_str(), Info.length()+1 );
00162     Position += Info.length()+1;
00163 }
00164 
00165 int ezSocketsPacket::ReadData( int Bytes, char * ToReplace )
00166 {
00167     if ( Bytes + Position >= Size )
00168         Bytes = (int)Size - (int)Position;
00169     if ( Bytes > 0 )
00170         memcpy( ToReplace, &Data[Position], Bytes );
00171     else 
00172         return 0;
00173     Position += Bytes;
00174     return Bytes;
00175 }
00176 
00177 void ezSocketsPacket::WriteData( const char * Info, unsigned int Length )
00178 {
00179     Grow( Length + Position );
00180     memcpy( &Data[Position], Info, Length ); 
00181     Position += Length;
00182 }
00183 
00184 void ezSocketsPacket::Grow( unsigned long iSizeTo )
00185 {
00186     if ( iSizeTo > Size )
00187     {
00188         char * OldData = Data;
00189         Data = (char*)malloc( iSizeTo );
00190         if ( OldData )
00191         {
00192             memcpy( Data, OldData, Size );
00193             free( OldData );
00194         }
00195         Size = iSizeTo;
00196     }
00197 }
00198 
00199 ezSockets::ezSockets()
00200 {
00201     memset (&addr,0,sizeof(addr)); //Clear the sockaddr_in structure
00202     
00203 #if defined(_WIN32) || defined(_XBOX) // Windows REQUIRES WinSock Startup
00204     WSAStartup( MAKEWORD(1,1), &wsda );
00205 #endif
00206     
00207     sock = INVALID_SOCKET;
00208     bBlocking = true;
00209     scks = new fd_set;
00210     times = new timeval;
00211     times->tv_sec = 0;
00212     times->tv_usec = 0;
00213     state = skDISCONNECTED;
00214 
00215     iBytesInPending = 0;
00216     pDataInTail = NULL;
00217     pDataInHead = NULL;
00218 }
00219 
00220 ezSockets::~ezSockets()
00221 {
00222     Close();
00223     delete scks;
00224     delete times;
00225 }
00226 
00227 bool ezSockets::Check()
00228 {
00229 #if !defined(XBOX)
00230     return sock > SOCKET_NONE;
00231 #else
00232     return sock != INVALID_SOCKET;
00233 #endif
00234 }
00235 
00236 bool ezSockets::Create(int Protocol, int Type)
00237 {
00238     state = skDISCONNECTED;
00239     sock = socket(AF_INET, Type, Protocol);
00240     lastCode = sock;
00241 #if !defined(XBOX)
00242     return sock > SOCKET_NONE;  //Socket must be Greater than 0
00243 #else
00244     return sock != INVALID_SOCKET;
00245 #endif
00246 }
00247 
00248 bool ezSockets::Bind(unsigned short port)
00249 {
00250     if(!Check())
00251         return false;
00252     
00253     addr.sin_family      = AF_INET;
00254     addr.sin_addr.s_addr = htonl(INADDR_ANY);
00255     addr.sin_port        = htons(port);
00256     lastCode = ::bind(sock,(struct sockaddr*)&addr, sizeof(addr));
00257     return !lastCode;
00258 }
00259 
00260 bool ezSockets::Listen( unsigned long depth )
00261 {
00262     lastCode = ::listen(sock, depth);
00263     if (lastCode == SOCKET_ERROR)
00264         return false;
00265     
00266     state = skLISTENING;
00267     return true;
00268 }
00269 
00270 bool ezSockets::Accept(ezSockets& socket)
00271 {
00272     if (!bBlocking && !CanRead())
00273         return false;
00274 
00275     int length = sizeof(socket);
00276     
00277     socket.sock = ::accept(sock,(struct sockaddr*) &socket.addr, 
00278                            (socklen_t*) &length);
00279     
00280     #if !( defined (_WIN32) || defined( _XBOX ) )
00281         char buf[INET_ADDRSTRLEN];
00282         inet_ntop(AF_INET, &socket.addr.sin_addr, buf, INET_ADDRSTRLEN);
00283         address = buf;
00284     #else
00285         address = inet_ntoa(socket.addr.sin_addr);
00286     #endif
00287 
00288     lastCode = socket.sock;
00289 
00290     if ( socket.sock == SOCKET_ERROR )
00291         return false;
00292     
00293     socket.state = skCONNECTED;
00294     return true;
00295 }
00296 
00297 ezSockets * ezSockets::Accept()
00298 {
00299     if (!bBlocking && !CanRead())
00300         return NULL;
00301 
00302     sockaddr_in local_addr;
00303     int length = sizeof(local_addr);
00304 
00305     int localsock = ::accept(sock,(struct sockaddr*) &local_addr, 
00306                            (socklen_t*) &length);
00307 
00308     if ( localsock == SOCKET_ERROR )
00309         return NULL;
00310     
00311     ezSockets * sNew = new ezSockets;
00312 
00313     #if !( defined (_WIN32) || defined( _XBOX ) )
00314         char buf[INET_ADDRSTRLEN];
00315         inet_ntop(AF_INET, &local_addr.sin_addr, buf, INET_ADDRSTRLEN);
00316         sNew->address = buf;
00317     #else
00318         sNew->address = inet_ntoa(local_addr.sin_addr);
00319     #endif      
00320 
00321     lastCode = localsock;
00322 
00323 
00324     sNew->bBlocking = bBlocking;
00325     sNew->lastCode = 0;
00326     sNew->mode = mode;
00327     sNew->pDataInHead = NULL;
00328     sNew->sock = localsock;
00329     sNew->state = skCONNECTED;
00330     return sNew;
00331 }
00332 
00333 void ezSockets::Close()
00334 {
00335     state = skDISCONNECTED;
00336 
00337     if ( pDataInHead )
00338     {
00339         pDataInHead->DestroyTree();
00340         delete pDataInHead;
00341         pDataInHead = NULL;
00342     }
00343 
00344 #if defined(WIN32) // The close socket command is different in Windows
00345     ::closesocket(sock);
00346 #else
00347     ::close(sock);
00348 #endif
00349 }
00350 
00351 bool ezSockets::Connect(const MString& host, unsigned short port)
00352 {
00353     if(!Check())
00354         return false;
00355     
00356 #if defined(_XBOX)
00357     if(!isdigit(host[0])) // don't do a DNS lookup for an IP address
00358     {
00359         XNDNS *pxndns = NULL;
00360         XNetDnsLookup(host.c_str(), NULL, &pxndns);
00361         while (pxndns->iStatus == WSAEINPROGRESS)
00362         {
00363             // Do something else while lookup is in progress
00364         }
00365         
00366         if (pxndns->iStatus == 0)
00367             memcpy(&addr.sin_addr, &pxndns->aina[0], sizeof(struct in_addr));
00368         else
00369             return false;
00370         
00371         XNetDnsRelease(pxndns);
00372     }
00373     else
00374         addr.sin_addr.s_addr = inet_addr(host.c_str());
00375 #else
00376     struct hostent* phe;
00377     phe = gethostbyname(host.c_str());
00378     if (phe == NULL)
00379         return false;
00380     memcpy(&addr.sin_addr, phe->h_addr, sizeof(struct in_addr));
00381 #endif 
00382     addr.sin_family = AF_INET;
00383     addr.sin_port   = htons(port);
00384     
00385     if(::connect(sock, (struct sockaddr*)&addr, sizeof(addr)) == SOCKET_ERROR)
00386         return false;
00387     
00388     state = skCONNECTED;
00389     return true;
00390 }
00391 
00392 bool ezSockets::CanRead()
00393 {
00394     FD_ZERO(scks);
00395     FD_SET((unsigned)sock, scks);
00396     
00397     return select(sock+1,scks,NULL,NULL,times) > 0;
00398 }
00399 
00400 bool ezSockets::DataAvailable()
00401 {
00402     if ( CanRead() )
00403         return true;
00404 
00405     //I think this is wrong, and is only the case with skGeneral
00406     if ( pDataInHead )
00407         if ( pDataInHead->PositionTAG != pDataInHead->Position )
00408             return true;
00409     return false;
00410 }
00411 
00412 bool ezSockets::IsError()
00413 {
00414     if (state == skERROR)
00415         return true;
00416     
00417     FD_ZERO(scks);
00418     FD_SET((unsigned)sock, scks);
00419     
00420     if (select(sock+1, NULL, NULL, scks, times) >=0 )
00421         return false;
00422     
00423     state = skERROR;
00424     return true;
00425 }
00426 
00427 bool ezSockets::CanWrite()
00428 {
00429     FD_ZERO(scks);
00430     FD_SET((unsigned)sock, scks);
00431     
00432     return select(sock+1, NULL, scks, NULL, times) > 0;
00433 }
00434 
00435 
00436 void ezSockets::SendData(const MString& outData)
00437 {
00438     if ( mode == skGeneral )
00439         pWriteData( outData.c_str(), outData.length() );
00440 }
00441 
00442 void ezSockets::SendData(const char *data, unsigned int bytes)
00443 {
00444     if ( mode == skGeneral )
00445         pWriteData( data, bytes );
00446 }
00447 
00448 int ezSockets::ReadData(char *data, unsigned int bytes)
00449 {
00450     if ( mode != skGeneral )
00451         return -1;
00452     int iRL = ReadLeftover( data, bytes );
00453     while ( iRL < (int)bytes )
00454     {
00455         int iGot = pReadData( data + iRL, ((int)bytes) - iRL );
00456         if ( iGot <= 0 )
00457             return iRL;
00458         iRL += iGot;
00459     }
00460     return iRL;
00461 }
00462 
00463 int ezSockets::PeekData(char *data, unsigned int bytes)
00464 {
00465     if ( mode != skGeneral )
00466         return -1;
00467 
00468     int iRL = 0;
00469     ReceiveGeneralData();
00470     ezSocketsPacket * tmp = pDataInHead;
00471 
00472     while ( tmp )
00473     {
00474         int iPotential = tmp->Size - tmp->Position;
00475         if ( iPotential > ((int)bytes)-iRL )
00476             iPotential = bytes-iRL;
00477         memcpy( data + iRL, tmp->Data + tmp->Position, iPotential );
00478         iRL += iPotential;
00479         if ( iRL >= ((int)bytes) )
00480             return iRL;
00481         tmp = tmp->Next;
00482     }
00483     return iRL;
00484 }
00485 
00486 //Yuck, this algorithm is kind of slow...
00487 bool ezSockets::ReadLine( MString & str )
00488 {
00489     if ( mode != skGeneral )
00490         return false;
00491 
00492     str = "";
00493     ReceiveGeneralData();
00494 
00495     ezSocketsPacket * tmp = pDataInHead;
00496 
00497     bool bFound = false;
00498     unsigned int i = 0;
00499 
00500     while ( tmp )
00501     {   
00502         for ( i = tmp->Position; i < tmp->PositionTAG; i++ )
00503             if ( tmp->Data[i] == '\n' )
00504             {
00505                 bFound = true;
00506                 break;
00507             }
00508         if ( !bFound )
00509             tmp = tmp->Next;
00510         else
00511             break;
00512     }
00513 
00514     if ( !bFound && !bBlocking )
00515         return false;
00516 
00517     if ( bFound )
00518         while ( pDataInHead != tmp )
00519         {
00520             str.append( pDataInHead->Data, pDataInHead->Size-pDataInHead->Position );
00521             pDataInHead = pDataInHead->Next;
00522         }
00523 
00524     if ( pDataInHead )
00525         if ( i != pDataInHead->Position )
00526         {
00527             str.append( pDataInHead->Data + pDataInHead->Position, i - pDataInHead->Position );
00528             pDataInHead->Position = i + 1;
00529         }
00530 
00531     //Keep waiting for more data
00532     if ( !bFound && bBlocking )
00533     {
00534         if ( pDataInHead )
00535             pDataInHead->Position = pDataInHead->PositionTAG;
00536         
00537         char tmp = '\0';
00538         while ( tmp != '\n' )
00539         {
00540             if ( ReadLeftover( &tmp, 1 ) != 1 )
00541                 return false;
00542             if ( tmp != '\n' )
00543                 str.append( &tmp, 1 );
00544         }
00545     }
00546 
00547     if ( str.length() > 0 )
00548         if ( str.c_str()[str.length()-1] == '\r' )
00549             str.resize ( str.length() - 1 );
00550 
00551     return true;
00552 }
00553 
00554 void ezSockets::WriteLine( const MString & str )
00555 {
00556     SendData( str.c_str(), str.length() );
00557     SendData( "\r\n", 2 );
00558 }
00559 
00560 int ezSockets::ReadLeftover( char * data, unsigned int maxbytes )
00561 {
00562     if ( mode != skGeneral )
00563         return -1;
00564 
00565     ReceiveGeneralData();
00566 
00567     int iPos = 0;
00568 
00569     while ( pDataInHead )
00570     {
00571         int iMemToRead = pDataInHead->PositionTAG - pDataInHead->Position;
00572         if ( iMemToRead == 0 )
00573             break;
00574         if ( iMemToRead > ( ((int)maxbytes) - iPos ) )
00575             iMemToRead = maxbytes - iPos;
00576 
00577         memcpy( data + iPos, pDataInHead->Data + pDataInHead->Position, iMemToRead );
00578 
00579         pDataInHead->Position += iMemToRead;
00580         iPos += iMemToRead;
00581 
00582         if ( pDataInHead->Position == pDataInHead->Size ) 
00583         {
00584             if ( pDataInHead == pDataInTail )
00585             {
00586                 delete pDataInHead;
00587                 pDataInHead = 0;
00588                 pDataInTail = 0;
00589                 return iPos;
00590             } else {
00591                 ezSocketsPacket * tmp = pDataInHead;
00592                 pDataInHead = pDataInHead->Next;
00593                 delete tmp;
00594             }
00595         }
00596 
00597         if ( iPos >= ((int)maxbytes) )
00598             return iPos;
00599     }
00600 
00601     if ( bBlocking )
00602     {
00603         int iRead = pReadData( Buffer, (ezSocketsBuffersize<maxbytes)?ezSocketsBuffersize:maxbytes );
00604         if ( iRead > 0 )
00605         {
00606             memcpy( data+iPos, Buffer, iRead );
00607             return iRead+iPos;
00608         }
00609         else
00610             return iPos;
00611     } else
00612         return iPos;
00613 }
00614 
00615 void ezSockets::ReceiveGeneralData( bool bForceBlock )
00616 {
00617     if ( mode == skGeneral )
00618     {
00619         while( CanRead() )
00620         {
00621             if( pDataInTail )
00622             {
00623                 if ( pDataInTail->Size <= pDataInTail->PositionTAG )
00624                 {
00625                     pDataInTail->Next = new ezSocketsPacket;
00626                     pDataInTail = pDataInTail->Next;
00627                     pDataInTail->Next = NULL;
00628                     pDataInTail->SetupPacket( ezSocketsBuffersize );
00629                     pDataInTail->PositionTAG = 0;
00630                 } else {
00631                     int rec = pReadData( pDataInTail->Data + pDataInTail->PositionTAG, pDataInTail->Size - pDataInTail->PositionTAG );
00632                     if ( rec>0 )
00633                         pDataInTail->PositionTAG += rec;
00634                     else 
00635                         break;
00636                 }
00637             }
00638             else
00639             {
00640                 pDataInTail = new ezSocketsPacket;
00641                 pDataInHead = pDataInTail;
00642                 pDataInHead->SetupPacket( ezSocketsBuffersize );
00643                 pDataInHead->PositionTAG = 0;
00644             }
00645         }
00646         return;
00647     } else if ( mode == skPackets ) 
00648     {
00649         bool bGotPack = false;
00650         if ( pDataInTail )
00651             if ( pDataInTail->PositionTAG >= 4 && pDataInTail->Position == pDataInTail->Size )
00652                 bGotPack = true;
00653         while ( CanRead() || ( bForceBlock && !bGotPack ) )
00654         {
00655             if ( !pDataInTail )
00656             {
00657                 pDataInHead = new ezSocketsPacket;
00658                 pDataInTail = pDataInHead;
00659                 pDataInTail->Next = NULL;
00660                 pDataInTail->PositionTAG = 0;   //0: Nothing received yet.
00661             }
00662             if ( pDataInTail->PositionTAG == 4 && pDataInTail->Size == pDataInTail->Position )
00663             {
00664                 pDataInTail->Next = new ezSocketsPacket;
00665                 pDataInTail = pDataInTail->Next;
00666                 pDataInTail->Next = NULL;
00667                 pDataInTail->PositionTAG = 0;
00668             }
00669             if ( pDataInTail->PositionTAG < 4 )
00670             {
00671                 int recv = pReadData( Buffer, 4 - pDataInTail->PositionTAG );
00672                 int cpos = 0;
00673                 unsigned int oldpos = pDataInTail->PositionTAG;
00674                 pDataInTail->PositionTAG+=recv;
00675                 if ( recv > 0 )
00676                 {
00677                     for ( ; oldpos < pDataInTail->PositionTAG; oldpos++ )
00678                     {
00679                         unsigned long j = (unsigned char)Buffer[cpos];
00680                         pDataInTail->Size += j<<(8*(3-oldpos));
00681                         cpos++;
00682                     }
00683                 } else
00684                     return;
00685                 if ( pDataInTail->PositionTAG == 4 )
00686                 {
00687                     pDataInTail->SetupPacket( pDataInTail->Size );
00688                     pDataInTail->Position = 0;
00689                 }
00690             } else
00691             {
00692                 int recv = pReadData( pDataInTail->Data + pDataInTail->Position, pDataInTail->Size - pDataInTail->Position );
00693                 if ( recv > 0 )
00694                     pDataInTail->Position += recv;
00695                 else
00696                     return;
00697             }
00698 
00699             if ( pDataInTail )
00700                 if ( pDataInTail->PositionTAG >= 4 && pDataInTail->Position == pDataInTail->Size )
00701                     bGotPack = true;
00702         }
00703     } else if ( mode == skUDP ) 
00704     {
00705         if ( CanRead() || bForceBlock )
00706         {
00707             int j = fromAddr.sin_addr.s_addr;
00708             int iRead = pReadData( Buffer, ezSocketsBuffersize );
00709             int pAddy = ntohl(fromAddr.sin_addr.s_addr);
00710             int pPort = ntohs(fromAddr.sin_port);
00711 
00712             if ( iRead>0 )
00713             {
00714                 if ( !pDataInTail )
00715                 {
00716                     pDataInHead = new ezSocketsPacket;
00717                     pDataInTail = pDataInHead;
00718                     pDataInTail->PositionTAG = 0;   //0: Nothing received yet.
00719                 } else {
00720                     ezSocketsPacket * tmp = pDataInTail;
00721                     pDataInTail = new ezSocketsPacket;
00722                     tmp->Next = pDataInTail;
00723                 }
00724 
00725                 pDataInTail->SetupPacket( iRead );
00726                 memcpy( pDataInTail->Data, Buffer, iRead );
00727                 pDataInTail->PositionTAG = pAddy;
00728                 pDataInTail->Port = pPort;
00729             }
00730         }
00731     }
00732 }
00733 
00734 void ezSockets::SendPack( const ezSocketsPacket &pPack )
00735 {
00736     //While this seems kind of dumb, re-copying the data and all
00737     //it does save us a potential extra packet. 
00738     //
00739     //Overall, it actually saves CPU.
00740     char * sToSend = (char*)malloc( pPack.Size + 4 );
00741     unsigned int nBytes = htonl( pPack.Size );
00742     memcpy( sToSend, &nBytes, 4 );
00743     memcpy( sToSend + 4, pPack.Data, pPack.Size );
00744     if( pPack.Port != 0 && mode == skUDP )
00745     {
00746         sockaddr_in to;
00747         to.sin_port = htons( pPack.Port );
00748         to.sin_family = AF_INET;
00749         to.sin_addr.s_addr = htonl( pPack.PositionTAG );
00750         memset( to.sin_zero, 0, 8 );
00751         bool j = (sendto( sock, sToSend, pPack.Size + 4 , 0, (sockaddr*)&to, sizeof( sockaddr_in ) )!=0);
00752     }
00753     else
00754         pWriteData( sToSend, pPack.Size + 4 );
00755     free( sToSend );
00756 }
00757 
00758 int ezSockets::ReadPack( ezSocketsPacket &pPack )
00759 {
00760     ReceiveGeneralData();
00761     if( pDataInHead )
00762     {
00763         if ( ( pDataInHead->Position == pDataInHead->Size || mode == skUDP ) && pDataInHead->PositionTAG >= 4 )
00764         {
00765             //Free up any necessiary data
00766             pPack.~ezSocketsPacket();
00767             pPack = (*pDataInHead);
00768 
00769             ezSocketsPacket * g = pDataInHead;
00770 
00771             pPack.Position = 0;
00772 
00773             if ( pDataInHead == pDataInTail )
00774             {
00775                 pDataInHead = NULL;
00776                 pDataInTail = NULL;
00777             } else 
00778                 pDataInHead = pDataInHead->Next;
00779 
00780             free( g );
00781 
00782             return 1;
00783         }
00784     }
00785     //Otherwise, wait until the packet is ready.
00786     if ( bBlocking )
00787     {
00788         ReceiveGeneralData( true );
00789         if( pDataInHead )
00790         {
00791             if ( ( pDataInHead->Position == pDataInHead->Size || mode == skUDP ) && pDataInHead->PositionTAG >= 4 )
00792             {
00793                 //Free up any necessiary data
00794                 pPack.~ezSocketsPacket();
00795                 pPack = (*pDataInHead);
00796 
00797                 ezSocketsPacket * g = pDataInHead;
00798                 pPack.Position = 0;
00799 
00800                 if ( pDataInHead == pDataInTail )
00801                 {
00802                     pDataInHead = NULL;
00803                     pDataInTail = NULL;
00804                 } else 
00805                     pDataInHead = pDataInHead->Next;
00806 
00807                 free( g );
00808 
00809                 return 1;
00810             }
00811         }
00812     }
00813 
00814     return 0;
00815 }
00816 
00817 int ezSockets::PeekPack( ezSocketsPacket &pPack )
00818 {
00819     ReceiveGeneralData();
00820     if( pDataInHead )
00821     {
00822         if ( pDataInHead->Position == pDataInHead->Size )
00823         {
00824             pPack.CopyPacket( *pDataInHead );
00825             pPack.Position = 0;
00826             return 1;
00827         }
00828     }
00829     return 0;
00830 }
00831 
00832 
00833 bool ezSockets::SetupForReuseAddr( bool bAllow )
00834 {
00835 #ifdef SO_REUSEADDR
00836 //  int optval = (bAllow)?1:0;
00837     char optval = (bAllow)?1:0;
00838     return setsockopt( sock, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval) ) >= 0;
00839 #else
00840     return false;
00841 #endif
00842 }
00843 
00844 bool ezSockets::SetupForMulticast( const MString & sAddressToJoin )
00845 {
00846 #ifdef IP_ADD_MEMBERSHIP
00847     ip_mreq jgrp;
00848     jgrp.imr_multiaddr.s_addr = inet_addr( sAddressToJoin.c_str() );
00849     jgrp.imr_interface.s_addr = htonl( INADDR_ANY );
00850     return setsockopt( sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, &jgrp, sizeof(jgrp) ) >= 0;
00851 #else
00852     return false;
00853 #endif
00854 }
00855 
00856 bool ezSockets::SetupForBroadcast( bool bBroadcast )
00857 {
00858 #ifdef SO_BROADCAST
00859     char optval = (bBroadcast)?1:0;
00860     return setsockopt( sock, SOL_SOCKET, SO_BROADCAST, &optval, sizeof( optval ) ) >= 0;
00861 #else
00862     return false;
00863 #endif
00864 }
00865 
00866 int ezSockets::pReadData(char* data, int maxsize )
00867 {
00868     if(state == skCONNECTED || state == skLISTENING)
00869         return recv(sock, data, maxsize, 0);
00870     
00871     int saddrinlen = sizeof(sockaddr_in);
00872 
00873     return recvfrom(sock, data, maxsize, 0, (sockaddr*)&fromAddr,
00874                     (socklen_t*)&saddrinlen);
00875 }
00876 
00877 int ezSockets::pWriteData(const char* data, int dataSize)
00878 {
00879 #if defined(WIN32)
00880     return send(sock, data, dataSize, 0);
00881 #else
00882     return send(sock, data, dataSize, MSG_NOSIGNAL);
00883 #endif
00884 }
00885 
00886 /* 
00887  * (c) 2003-2006 Josh Allen, Charles Lohr, and Adam Lowman
00888  * All rights reserved.
00889  * 
00890  * Permission is hereby granted, free of charge, to any person obtaining a
00891  * copy of this software and associated documentation files (the
00892  * "Software"), to deal in the Software without restriction, including
00893  * without limitation the rights to use, copy, modify, merge, publish,
00894  * distribute, and/or sell copies of the Software, and to permit persons to
00895  * whom the Software is furnished to do so, provided that the above
00896  * copyright notice(s) and this permission notice appear in all copies of
00897  * the Software and that both the above copyright notice(s) and this
00898  * permission notice appear in supporting documentation.
00899  * 
00900  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
00901  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00902  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
00903  * THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
00904  * INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
00905  * OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
00906  * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
00907  * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
00908  * PERFORMANCE OF THIS SOFTWARE.
00909  */

Hosted by SourceForge.net Logo