sock.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002                           sock.cpp  -  description
00003                              -------------------
00004     begin                : Thu Dec 9 2004
00005     copyright            : (C) 2004 by VooDooMan
00006     email                : vdmfun@hotmail.com
00007  ***************************************************************************/
00008 
00009 /***************************************************************************
00010 
00011 VooDoo cIRCle - an IRC (ro)bot
00012 
00013 
00014 Copyright (C) 2004 by Marian VooDooMan Meravy (vdmfun@hotmail.com)
00015 
00016 This program is free software; you can redistribute it and/or
00017 modify it under the terms of the GNU General Public License
00018 as published by the Free Software Foundation; either version 2
00019 of the License, or (at your option) any later version.
00020 
00021 This program is distributed in the hope that it will be useful,
00022 but WITHOUT ANY WARRANTY; without even the implied warranty of
00023 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00024 GNU General Public License for more details.
00025 
00026 You should have received a copy of the GNU General Public License
00027 along with this program; if not, write to the Free Software
00028 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00029 
00030 ****************************************************************************/
00031 
00032 /*!
00033     \file
00034     \brief Provides low-level IP socket communication
00035 */
00036 
00037 //---------------------------------------------------------------------------
00038 
00039 #include <vector>
00040 #include <list>
00041 #include <string>
00042 #include <stdio.h>
00043 #ifdef _WIN32
00044 #   define _WINSOCKAPI_
00045 #   include <windows.h>
00046 #else
00047 #    include <sys/time.h>
00048 #    include <sys/types.h>
00049 #    include <unistd.h>
00050 #endif
00051 
00052 #pragma hdrstop
00053 
00054 #include "sock.h"
00055 
00056 #include "params.h"
00057 
00058 //#include "stdafx.h"
00059 
00060 //---------------------------------------------------------------------------
00061 #ifndef _MSC_VER
00062 #pragma package(smart_init)
00063 #endif
00064 
00065 using namespace std;
00066 
00067 #ifdef _WIN32
00068 #   define socklen_t int
00069 #endif
00070 
00071 extern size_t sock_lo_send(s_socket& socket, char* buff, size_t len);
00072 extern size_t sock_lo_recv(s_socket& socket, char* buff, size_t len);
00073 extern size_t sock_lo_get_input_amount(s_socket& socket, char* buff, size_t len);
00074 
00075 /*!
00076     \brief Stores data to send/receive later
00077     \author VooDooMan
00078     \version 1
00079     \date 2004
00080 */
00081 struct s_data {
00082     bool closed;                        //!< Idicates that connection has been closed (if this is true, data && len are undefined)
00083     //int error;                          //!< Idicates that connection has error (if this is non-zero, data && len are undefined)
00084     size_t len;                         //!< Length of data
00085     char* data;                         //!< Data
00086 
00087     s_data()
00088     {
00089         closed=false;
00090         //error=0;
00091         len=0;
00092         data=NULL;
00093     }
00094 };
00095 
00096 /*!
00097     \brief Stores data to send later
00098     \author VooDooMan
00099     \version 2
00100     \date 2004, 2005
00101 */
00102 struct s_send_later {
00103     //bool has_error;                         //!< Set to true, if we have data, but there's an error on the socket, or socket has been closed (by remote host)
00104     //int last_error;                         //!< Stores last error code
00105     s_socket socket;                        //!< Socket handle
00106     list<s_data> data;                      //!< Array of data packets
00107 
00108     time_t last_send;                       //!< Timestamp of last send operation
00109 
00110     s_send_later()
00111     {
00112         //has_error=false;
00113         socket.clear();
00114         data.clear();
00115         //last_error=0;
00116         last_send=time(NULL);
00117     }
00118 };
00119 
00120 /*!
00121     \brief Stores data to receive later
00122     \author VooDooMan
00123     \version 2
00124     \date 2004, 2005
00125 */
00126 struct s_receive_later {
00127     bool has_error;                         //!< Set to true, if we have data, but there's an error on the socket, or socket has been closed (by remote host)
00128     int last_error;                         //!< Stores last error code
00129     s_socket socket;                        //!< Socket handle
00130     bool using_window;                      //!< Set to true if this socket is using message window callback to receive data
00131     list<s_data> data;                      //!< Array of data packets
00132 
00133     time_t last_recv;                       //!< Timestamp of last receive operation
00134 
00135     s_receive_later()
00136     {
00137         has_error=false;
00138         socket.clear();
00139         using_window=false;
00140         data.clear();
00141         last_error=0;
00142         last_recv=time(NULL);
00143     }
00144 };
00145 
00146 vector<s_send_later> send_later;            //!< Packets to send later
00147 vector<s_receive_later> receive_later;      //!< Packets to receive later
00148 
00149 #ifdef _WIN32
00150 #   define WM_TCPASYNCSELECT (WM_USER+123)     //!< Our own window message for receiving data (Windows(TM) only)
00151 
00152 /*!
00153     \brief Callback windows procedure for receiving data (Windows(TM) only)
00154     \author VooDooMan
00155     \version 2
00156     \date 2005
00157     \param hwnd Handle of window
00158     \param uMsg Message
00159     \param wParam Parameter #1
00160     \param lParam Parameter #2
00161     \return Should return zero if message has been processed
00162 */
00163 LRESULT CALLBACK WndProc(/*HWND*/void* hwnd, /*UINT*/int uMsg, /*WPARAM*/int wParam, /*LPARAM*/int lParam)
00164 {
00165     if(uMsg==WM_NCCREATE)
00166         return true;
00167 
00168     char* Buf=NULL;
00169 
00170     try {
00171         if(uMsg!=WM_TCPASYNCSELECT)
00172             return 0;
00173         int ErrorCode=WSAGETSELECTERROR(lParam);
00174         if(ErrorCode>WSABASEERR)
00175             return 0;
00176 
00177         int SelectEvent=WSAGETSELECTEVENT(lParam);
00178         switch (SelectEvent) {
00179             case FD_READ:
00180                 {
00181                     unsigned int max_len=1024*64;
00182                     Buf=new char[max_len];
00183                     s_socket Sock;
00184                     Sock.clear();
00185                     Sock.handle=wParam;
00186                     //int Size=recv(Sock.handle,Buf,max_len,0);
00187                     int Size=recvfrom(Sock.handle,Buf,max_len,0,NULL,NULL);
00188                     if(Size==SOCKET_ERROR) {
00189                         //closesocket(Sock.handle);
00190                         delete[] Buf;
00191                         Buf=NULL;
00192                         vector<s_receive_later>::iterator i1;
00193                         for(i1=receive_later.begin(); i1!=receive_later.end(); i1++)
00194                             if((*i1).socket.handle==Sock.handle) {
00195                                 int la=WSAGetLastError();
00196                                 if(la!=WSAEWOULDBLOCK && !(*i1).has_error) {
00197                                     (*i1).has_error=true;
00198                                     (*i1).last_error=la;
00199                                 }
00200                             }
00201                         return 0;
00202                     }
00203                     if(Size>0)
00204                         Sock.last_io=time(NULL);
00205                     vector<s_receive_later>::iterator i1;
00206                     for(i1=receive_later.begin(); i1!=receive_later.end(); i1++) {
00207                         if((*i1).socket.handle==Sock.handle) {
00208                             if((*i1).socket.last_io<Sock.last_io)
00209                                 (*i1).socket.last_io=Sock.last_io;
00210                             else
00211                                 Sock.last_io=(*i1).socket.last_io;
00212 
00213                             if(Size>0)
00214                                 (*i1).last_recv=time(NULL);
00215 
00216                             s_data d;
00217                             char* b=new char[Size];
00218                             memcpy(b,Buf,Size);
00219                             d.closed=false;
00220                             //d.error=0;
00221                             d.data=b;
00222                             d.len=Size;
00223                             (*i1).data.push_back(d);
00224                             break;
00225                         }
00226                     }
00227                     delete[] Buf;
00228                     Buf=NULL;
00229                 }
00230                 break;
00231             case FD_CLOSE:
00232                 {
00233                     s_socket Sock;
00234                     Sock.clear();
00235                     Sock.handle=wParam;
00236                     vector<s_receive_later>::iterator i1;
00237                     for(i1=receive_later.begin(); i1!=receive_later.end(); i1++) {
00238                         if((*i1).socket.handle==Sock.handle) {
00239                             s_data d;
00240                             d.closed=true;
00241                             //d.error=0;
00242                             d.data=NULL;
00243                             d.len=0;
00244                             (*i1).data.push_back(d);
00245                             break;
00246                         }
00247                     }
00248                 }
00249                 break;
00250         }
00251     } catch (...) {}
00252     if(Buf) {
00253         delete[] Buf;
00254         Buf=NULL;
00255     }
00256     return 0;
00257 }
00258 
00259 /*!
00260     \brief Allocates window handle (Windows(TM) only)
00261     \author VooDooMan
00262     \version 1
00263     \date 2004
00264     \param m Pointer to window callback message procedure
00265     \returns Window handle or NULL if something goes wrong
00266 */
00267 HWND AllocateHWnd(void* m)
00268 {
00269     WNDCLASSEXA c;
00270     memset(&c,0,sizeof(c));
00271     char tmp[1024];
00272     tmp[0]=0;
00273     for(int ii=0; ii<5; ii++) {
00274         int i=rand();
00275         char tmp2[16];
00276         strcat(tmp,ltoa(i,tmp2,16));
00277     }
00278     c.lpszClassName=tmp;
00279     c.lpfnWndProc=(WNDPROC)m;
00280     c.cbSize=sizeof(c);
00281     RegisterClassExA(&c);
00282     HWND h=CreateWindowExA(0,tmp,"",0,0,0,0,0,HWND_MESSAGE,NULL,NULL,NULL);
00283     SetWindowLongA(h, GWL_WNDPROC,(LONG)m);
00284     return h;
00285 }
00286 #endif
00287 
00288 /*!
00289     \brief Writes data to connected socket
00290     \author VooDooMan
00291     \version 2
00292     \date 2005
00293     \param socket Socket handle of connected socket
00294     \param data Buffer to write
00295     \param size Size of buffer
00296     \param error_code Returns OS's socket error
00297     \return Returns amount of sent data in bytes
00298 */
00299 unsigned int sock_send(s_socket& socket, const char* data, unsigned int size, int& error_code)
00300 {
00301     {
00302         {
00303             {
00304             again:
00305                 bool got=false;
00306                 vector<s_send_later>::iterator i1;
00307                 for(i1=send_later.begin(); i1!=send_later.end(); i1++) {
00308                     if((*i1).socket.handle==socket.handle) {
00309                         if((*i1).socket.last_io<socket.last_io)
00310                             (*i1).socket.last_io=socket.last_io;
00311                         else
00312                             socket.last_io=(*i1).socket.last_io;
00313                         (*i1).last_send=time(NULL);
00314                         got=true;
00315                         break;
00316                     }
00317                 }
00318                 if(!got) {
00319                     s_send_later s;
00320                     //s.has_error=false;
00321                     s.socket=socket;
00322                     //s.last_error=0;
00323                     s.last_send=time(NULL);
00324                     send_later.push_back(s);
00325                     goto again;
00326                 }
00327                 s_data d;
00328                 d.closed=false;
00329                 //d.error=0;
00330                 d.len=size;
00331                 d.data=new char[size];
00332                 memcpy(d.data,data,size);
00333                 (*i1).data.push_back(d);
00334 
00335                 error_code=0;
00336                 return size;
00337             }
00338         }
00339     }
00340 }
00341 
00342 /*!
00343     \brief Reads data from connected socket
00344     \author VooDooMan
00345     \version 2
00346     \date 2005
00347     \param socket Socket handle of connected socket
00348     \param data Buffer to be filled up to "size" bytes
00349     \param size Size of buffer (maximum bytes to be read)
00350     \param error_code Returns OS's socket error
00351     \param connection_closed Returns true if data was successfuly read, but remote host closed the connection (this is not error and read of data is working correctly)
00352     \return Returns amount of read data in bytes
00353 */
00354 size_t sock_read(s_socket& socket, char* data, size_t size, int& error_code, bool& connection_closed)
00355 {
00356     error_code=0;
00357     connection_closed=false;
00358     {
00359         vector<s_receive_later>::iterator i1;
00360         for(i1=receive_later.begin(); i1!=receive_later.end(); i1++) {
00361             if((*i1).socket.handle==socket.handle) {
00362                 if((*i1).socket.last_io<socket.last_io)
00363                     (*i1).socket.last_io=socket.last_io;
00364                 else
00365                     socket.last_io=(*i1).socket.last_io;
00366 
00367                 if((*i1).data.begin()==(*i1).data.end() && (*i1).last_error) {
00368                     error_code=(*i1).last_error;
00369                     return 0;
00370                 }
00371 
00372                 list<s_data>::iterator i2;
00373                 connection_closed=false;
00374 again:
00375                 for(i2=(*i1).data.begin(); i2!=(*i1).data.end(); i2++) {
00376                     (*i1).last_recv=time(NULL);
00377 
00378                     error_code=0;
00379                     if((*i2).closed) {
00380                         connection_closed=true;
00381                         (*i1).data.pop_front();
00382                         goto again;
00383                     }
00384                     connection_closed=false;
00385                     /*error_code=(*i2).error;
00386                     if(error_code || connection_closed)
00387                         return 0;*/
00388 
00389                     size_t l=size;
00390                     if((*i2).len<=l) {
00391                         l=(*i2).len;
00392                         if((*i2).len)
00393                             memcpy(data,(*i2).data,l);
00394                         delete[] (*i2).data;
00395                         (*i1).data.pop_front();
00396                         error_code=0;
00397                         return l;
00398                     }
00399                     if((*i2).len>l) {
00400                         memcpy(data,(*i2).data,l);
00401                         char* buf=new char[(*i2).len-l];
00402                         memcpy(buf,&((*i2).data[l]),(*i2).len-l);
00403                         delete[] (*i2).data;
00404                         (*i2).len-=l;
00405                         (*i2).data=buf;
00406                         error_code=0;
00407                         return l;
00408                     }
00409                 }
00410                 error_code=0;
00411                 //connection_closed=false;
00412                 return 0;
00413             }
00414         }
00415     }
00416 
00417     return 0;
00418 }
00419 
00420 /*!
00421     \brief Puts buffer back to queue as if it weren't read
00422     \author VooDooMan
00423     \version 2
00424     \date 2005
00425     \param socket Socket handle of connected socket
00426     \param data Buffer to be filled up to "size" bytes
00427     \param size Size of buffer (maximum bytes to be read)
00428 */
00429 void sock_unread(s_socket& socket, char* data, size_t size)
00430 {
00431     {
00432         vector<s_receive_later>::iterator i1;
00433         for(i1=receive_later.begin(); i1!=receive_later.end(); i1++) {
00434             if((*i1).socket.handle==socket.handle) {
00435                 if((*i1).socket.last_io<socket.last_io)
00436                     (*i1).socket.last_io=socket.last_io;
00437                 else
00438                     socket.last_io=(*i1).socket.last_io;
00439                 s_data d;
00440                 d.closed=false;
00441                 //d.error=0;
00442                 d.data=data;
00443                 d.len=size;
00444                 (*i1).data.push_front(d);
00445                 return;
00446             }
00447         }
00448     }
00449 }
00450 
00451 /*!
00452     \brief Get size of input buffer on socket
00453     \author VooDooMan
00454     \version 1
00455     \date 2004
00456     \param socket Socket handle
00457     \return Number of bytes waiting to receive
00458 */
00459 size_t sock_get_receive_size(s_socket& socket)
00460 {
00461     size_t result=0;
00462 
00463     vector<s_receive_later>::iterator i1;
00464     for(i1=receive_later.begin(); i1!=receive_later.end(); i1++) {
00465         if((*i1).socket.handle==socket.handle) {
00466             if((*i1).socket.last_io<socket.last_io)
00467                 (*i1).socket.last_io=socket.last_io;
00468             else
00469                 socket.last_io=(*i1).socket.last_io;
00470 
00471             list<s_data>::iterator i2;
00472             for(i2=(*i1).data.begin(); i2!=(*i1).data.end(); i2++) {
00473                 if(!(*i2).closed /*&& !(*i2).error*/)
00474                     result+=(*i2).len;
00475             }
00476             break;
00477         }
00478     }
00479     return result;
00480 }
00481 
00482 /*!
00483     \brief Sends and receive all pending data (in the cache), should be called in loop
00484     \author VooDooMan
00485     \version 2
00486     \date 2005
00487 */
00488 void sock_send_cache()
00489 {
00490     unsigned int _tmp_size_=1024*64;
00491     char* _tmp_=new char[_tmp_size_];
00492 
00493     vector<s_receive_later>::iterator i2;
00494     for(i2=receive_later.begin(); i2!=receive_later.end(); i2++) {
00495         {
00496             {
00497                 // do a dummy operation
00498                 size_t res=sock_lo_get_input_amount((*i2).socket,_tmp_,_tmp_size_);
00499 
00500                 int error_code=WSAGetLastError();
00501                 if(res!=SOCKET_ERROR)
00502                     error_code=0;
00503                 if(error_code && error_code!=WSAEWOULDBLOCK) {
00504                     if(!(*i2).has_error) {
00505                         (*i2).has_error=true;
00506                         (*i2).last_error=error_code;
00507                     }
00508                 }
00509             }
00510         }
00511 
00512         if((*i2).using_window)
00513             continue;
00514         char tmp[1024];
00515         socklen_t tmp2=1024;
00516         getsockopt((*i2).socket.handle,SOL_SOCKET,SO_ERROR,tmp,&tmp2);
00517 
00518         for(;;) {
00519             {
00520                 // do a dummy operation
00521                 size_t res=sock_lo_get_input_amount((*i2).socket,_tmp_,_tmp_size_);
00522 
00523                 int error_code=WSAGetLastError();
00524                 if(res!=SOCKET_ERROR)
00525                     error_code=0;
00526                 if(error_code && error_code!=WSAEWOULDBLOCK) {
00527                     if(!(*i2).has_error) {
00528                         (*i2).has_error=true;
00529                         (*i2).last_error=error_code;
00530                     }
00531                 }
00532             }
00533 
00534             fd_set a;
00535             timeval t;
00536 
00537             t.tv_sec=0;
00538             t.tv_usec=1;
00539 
00540             FD_ZERO(&a);
00541             FD_SET((*i2).socket.handle,&a);
00542 
00543             int i=select((int)(*i2).socket.handle+1,&a,NULL,NULL,&t);
00544             if(i==0)
00545                 break;
00546 
00547             unsigned int max_size=1024*64;
00548             char* buf=new char[max_size];
00549             //max_size=sock_lo_get_input_amount((*i2).socket,buf,max_size);
00550             size_t size_=sock_lo_recv((*i2).socket,buf,max_size);
00551             if(size_==SOCKET_ERROR) {
00552                 delete[] buf;
00553                 int error_code=WSAGetLastError();
00554                 if(error_code==WSAEWOULDBLOCK)
00555                     break;
00556                 if(!(*i2).has_error) {
00557                     (*i2).has_error=true;
00558                     (*i2).last_error=error_code;
00559                     break;
00560                 }
00561                 break;
00562             }
00563             if(size_>0) {
00564                 (*i2).socket.last_io=time(NULL);
00565                 /*
00566                 vector<s_send_later>::iterator i1;
00567                 i1=send_later.begin();
00568                 if(i1!=send_later.end()) {
00569                     (*i1).socket.last_io=time(NULL);
00570                     (*i1).last_send=time(NULL);
00571                 }
00572                 */
00573                 (*i2).socket.last_io=time(NULL);
00574                 (*i2).last_recv=time(NULL);
00575             }
00576             if(size_==0) {
00577                 delete[] buf;
00578                 if(!(*i2).has_error) {
00579                     s_data d;
00580                     d.closed=true;
00581                     //d.error=0;
00582                     (*i2).data.push_back(d);
00583                     (*i2).has_error=true;
00584                 }
00585                 break;
00586             }
00587             if(size_) {
00588                 s_data d;
00589                 d.closed=false;
00590                 //d.error=0;
00591                 d.len=size_;
00592                 d.data=buf;
00593                 (*i2).data.push_back(d);
00594             }
00595         }
00596     }
00597 
00598     vector<s_send_later>::iterator i1;
00599     for(i1=send_later.begin(); i1!=send_later.end(); i1++) {
00600     again:
00601         list<s_data>::iterator i2;
00602         try {
00603             i2=(*i1).data.begin();
00604         } catch(...) {
00605             continue;
00606         }
00607         for(i2=(*i1).data.begin(); i2!=(*i1).data.end(); i2++) {
00608             size_t l=1024;
00609             if((*i2).len<l)
00610                 l=(*i2).len;
00611             size_t Sent=sock_lo_send((*i1).socket,(*i2).data,l);
00612             if(Sent==SOCKET_ERROR) {
00613                 int la=WSAGetLastError();
00614                 if(la==WSAEWOULDBLOCK)
00615                     break;
00616                 /*if(!(*i1).has_error)*/ {
00617                     vector<s_receive_later>::iterator i2;
00618                     for(i2=receive_later.begin(); i2!=receive_later.end(); i2++)
00619                         if((*i2).socket.handle==(*i1).socket.handle) {
00620                             (*i2).has_error=true;
00621                             if((*i2).last_error==0)
00622                                 (*i2).last_error=la;
00623                             break;
00624                         }
00625                     /*s_data d;
00626                     d.closed=false;
00627                     d.error=la;
00628                     (*i1).data.push_back(d);
00629                     (*i1).has_error=true;*/
00630                 }
00631                 break;
00632             }
00633             if(Sent>0) {
00634                 (*i1).socket.last_io=time(NULL);
00635                 /*
00636                 vector<s_receive_later>::iterator i2;
00637                 i2=receive_later.begin();
00638                 if(i2!=receive_later.end())
00639                     (*i2).socket.last_io=time(NULL);
00640                 */
00641                 (*i1).socket.last_io=time(NULL);
00642                 (*i1).last_send=time(NULL);
00643             }
00644             if(Sent<(*i2).len) {
00645                 char* buf=new char[(*i2).len-Sent];
00646                 memcpy(buf,&(*i2).data[Sent],(*i2).len-Sent);
00647                 delete[] (*i2).data;
00648                 (*i2).len-=Sent;
00649                 (*i2).data=buf;
00650             } else {
00651                 delete[] (*i2).data;
00652                 (*i1).data.pop_front();
00653             }
00654             goto again;
00655         }
00656     }
00657     delete[] _tmp_;
00658 }
00659 
00660 /*!
00661     \brief Creates cache entries
00662     \author VooDooMan
00663     \version 1
00664     \date 2004
00665     \param socket Socket handle to create cache for
00666     \param using_window Are we using window message callback to receive? (Windows(TM) only)
00667 */
00668 void sock_create_later(s_socket& socket, bool using_window)
00669 {
00670 #ifndef _WIN32
00671     using_window=false;
00672 #endif
00673     s_receive_later r;
00674     r.has_error=false;
00675     r.socket=socket;
00676     r.using_window=using_window;
00677     r.last_error=0;
00678     r.last_recv=time(NULL);
00679     receive_later.push_back(r);
00680 
00681     s_send_later s;
00682     //s.has_error=false;
00683     s.socket=socket;
00684     //s.last_error=0;
00685     s.last_send=time(NULL);
00686     send_later.push_back(s);
00687 }
00688 
00689 /*!
00690     \brief Sets asynchronous mode for the socket
00691     \author VooDooMan
00692     \version 2
00693     \date 2005
00694     \param socket Socket handle
00695 */
00696 void sock_async(s_socket& socket)
00697 {
00698 #ifdef _WIN32
00699 #   ifndef __GNUC__
00700     HWND WindowHandle=AllocateHWnd(WndProc);
00701 #   else
00702     HWND WindowHandle=AllocateHWnd((void*)WndProc);
00703 #   endif
00704     socket.wnd=WindowHandle;
00705     WSAAsyncSelect(socket.handle,WindowHandle,WM_TCPASYNCSELECT,FD_READ | FD_CLOSE);
00706 #else
00707     sock_set_blocking(socket,true);
00708 #endif
00709 }
00710 
00711 /*!
00712     \brief Flushes cache data (receives and sends)
00713     \author VooDooMan
00714     \version 2
00715     \date 2005
00716     \param socket Socket handle to flush cache for
00717 */
00718 void sock_flush_later(s_socket& socket)
00719 {
00720     vector<s_send_later>::iterator i1;
00721     for(i1=send_later.begin(); i1!=send_later.end(); i1++) {
00722         if((*i1).socket.handle==socket.handle) {
00723             if((*i1).socket.last_io<socket.last_io)
00724                 (*i1).socket.last_io=socket.last_io;
00725             else
00726                 socket.last_io=(*i1).socket.last_io;
00727 
00728             (*i1).last_send=time(NULL);
00729 
00730             list<s_data>::iterator i2;
00731         again:
00732             for(i2=(*i1).data.begin(); i2!=(*i1).data.end(); i2++) {
00733                 if(!(*i2).closed /*&& !(*i2).error*/) {
00734                     size_t l=1024;
00735                     if((*i2).len<l)
00736                         l=(*i2).len;
00737                     size_t Sent=sock_lo_send((*i1).socket,(*i2).data,l);
00738                     if(Sent==SOCKET_ERROR) {
00739                         int la=WSAGetLastError();
00740                         if(la!=WSAEWOULDBLOCK) {
00741                             vector<s_receive_later>::iterator i3;
00742                             for(i3=receive_later.begin(); i3!=receive_later.end(); i3++)
00743                                 if((*i3).socket.handle==(*i1).socket.handle) {
00744                                     (*i3).has_error=true;
00745                                     if((*i3).last_error==0)
00746                                         (*i3).last_error=la;
00747                                     break;
00748                                 }
00749                             //(*i1).has_error=true;
00750                             (*i1).data.pop_front();
00751                             goto again;
00752                         } else {
00753                             break;
00754                         }
00755                     }
00756                     if(Sent>0)
00757                         (*i1).socket.last_io=time(NULL);
00758                     if(Sent<(*i2).len) {
00759                         char* buf=new char[(*i2).len-Sent];
00760                         memcpy(buf,&(*i2).data[Sent],(*i2).len-Sent);
00761                         delete[] (*i2).data;
00762                         (*i2).len-=Sent;
00763                         (*i2).data=buf;
00764                     } else {
00765                         delete[] (*i2).data;
00766                         (*i1).data.pop_front();
00767                     }
00768                     goto again;
00769                 }
00770 
00771                 (*i1).data.pop_front();
00772                 goto again;
00773             }
00774             break;
00775         }
00776     }
00777     vector<s_receive_later>::iterator i2;
00778     for(i2=receive_later.begin(); i2!=receive_later.end(); i2++) {
00779         if((*i2).socket.handle==socket.handle) {
00780             if((*i2).socket.last_io<socket.last_io)
00781                 (*i2).socket.last_io=socket.last_io;
00782             else
00783                 socket.last_io=(*i2).socket.last_io;
00784 
00785             list<s_data>::iterator i3;
00786         again2:
00787             for(i3=(*i2).data.begin(); i3!=(*i2).data.end(); i3++) {
00788                 if(!(*i3).closed /*&& !(*i3).error*/)
00789                     delete[] (*i3).data;
00790                 (*i2).data.pop_front();
00791                 goto again2;
00792             }
00793             break;
00794         }
00795     }
00796 }
00797 
00798 /*!
00799     \brief Frees cache data (receives and sends), without send / receive
00800     \author VooDooMan
00801     \version 1
00802     \date 2004
00803     \param socket Socket handle to free cache for
00804 */
00805 void sock_erase_later(s_socket& socket)
00806 {
00807     vector<s_send_later>::iterator i1;
00808     for(i1=send_later.begin(); i1!=send_later.end(); i1++) {
00809         if((*i1).socket.handle==socket.handle) {
00810             list<s_data>::iterator ii;
00811 again_1:
00812             for(ii=(*i1).data.begin(); ii!=(*i1).data.end(); ii++) {
00813                 if(!(*ii).closed)
00814                     delete[] (*ii).data;
00815                 (*i1).data.erase(ii);
00816                 goto again_1;
00817             }
00818             send_later.erase(i1);
00819             break;
00820         }
00821     }
00822     vector<s_receive_later>::iterator i2;
00823     for(i2=receive_later.begin(); i2!=receive_later.end(); i2++) {
00824         if((*i2).socket.handle==socket.handle) {
00825             if((*i2).socket.last_io<socket.last_io)
00826                 (*i2).socket.last_io=socket.last_io;
00827             else
00828                 socket.last_io=(*i2).socket.last_io;
00829 
00830             list<s_data>::iterator ii;
00831 again_2:
00832             for(ii=(*i2).data.begin(); ii!=(*i2).data.end(); ii++) {
00833                 if(!(*ii).closed)
00834                     delete[] (*ii).data;
00835                 (*i1).data.erase(ii);
00836                 goto again_2;
00837             }
00838 
00839             receive_later.erase(i2);
00840             break;
00841         }
00842     }
00843 }
00844 
00845 /*!
00846     \brief Cancels caching
00847     \author VooDooMan
00848     \version 1
00849     \date 2004
00850     \param socket Socket handle
00851 */
00852 void sock_cancel_caching(s_socket& socket)
00853 {
00854     sock_flush_later(socket);
00855     sock_erase_later(socket);
00856 #ifdef _WIN32
00857     WSAAsyncSelect(socket.handle,socket.wnd,0,0);
00858 #endif
00859 }
00860 
00861 /*!
00862     \brief Returns last read/receive or send timestamp on socket
00863     \author VooDooMan
00864     \version 1
00865     \date 2005
00866     \param socket Socket handle
00867     \param mode Set to 'r' to get timestamp of last receive; set to 's' to get time of last send; set to 'a' (default) (stands for "all") to get most recent timestamp on both send and receive
00868     \return Timestamp of last send or receive on socket
00869     \warning If argument "mode" contain neither 'r', nor 's', nor 'a', the returned value is zero
00870 */
00871 time_t sock_get_last_io(s_socket& socket, char mode /* ='a' */)
00872 {
00873     time_t last_io=0;
00874 
00875     if(mode=='r') {
00876         vector<s_receive_later>::iterator i2;
00877         for(i2=receive_later.begin(); i2!=receive_later.end(); i2++)
00878             if((*i2).socket.handle==socket.handle) {
00879                 last_io=(*i2).last_recv;
00880                 break;
00881             }
00882     }
00883 
00884     if(mode=='s') {
00885         vector<s_send_later>::iterator i2;
00886         for(i2=send_later.begin(); i2!=send_later.end(); i2++)
00887             if((*i2).socket.handle==socket.handle) {
00888                 last_io=(*i2).last_send;
00889                 break;
00890             }
00891     }
00892 
00893     if(mode=='a') {
00894         last_io=socket.last_io;
00895 
00896         vector<s_receive_later>::iterator i2;
00897         for(i2=receive_later.begin(); i2!=receive_later.end(); i2++)
00898             if((*i2).socket.handle==socket.handle) {
00899                 if(last_io<(*i2).socket.last_io)
00900                     last_io=(*i2).socket.last_io;
00901                 if(last_io<(*i2).last_recv)
00902                     last_io=(*i2).last_recv;
00903                 break;
00904             }
00905 
00906         vector<s_send_later>::iterator i1;
00907         for(i1=send_later.begin(); i1!=send_later.end(); i1++)
00908             if((*i1).socket.handle==socket.handle) {
00909                 if(last_io<(*i1).socket.last_io)
00910                     last_io=(*i1).socket.last_io;
00911                 if(last_io<(*i1).last_send)
00912                     last_io=(*i1).last_send;
00913                 break;
00914             }
00915     }
00916 
00917     return last_io;
00918 }
00919 
00920 /*!
00921     \brief Discovers type of address
00922     \author VooDooMan
00923     \version 1
00924     \date 2005
00925     \param host IP of host name
00926     \retval 0 Given host is DNS name of host
00927     \retval 4 Given host is numeric IPv4 address
00928     \retval 6 Given host is numeric IPv6 address
00929 */
00930 int sock_get_address_type(string host)
00931 {
00932     unsigned int i1, i2, i3, i4;
00933     int x=sscanf(host.c_str(),"%u.%u.%u.%u", &i1, &i2, &i3, &i4);
00934     if(x==4)
00935         return 4;
00936     if(host.find(":",0)!=string::npos)
00937         return 6;
00938     return 0;
00939 }
00940 

Generated on Sun Jul 10 03:23:02 2005 for VooDoo cIRCle by doxygen 1.4.3

Hosted by SourceForge.net Logo