Main Page | File List

blockingsocket.cpp

00001 // Copyright (c) 1999 Lee Patterson
00002 // leepatterson@home.com
00003 
00004 // blocksock.cpp (CBlockingSocketException, CBlockingSocket, CHttpBlockingSocket)
00005 //#include <winsock.h>
00006 #include <assert.h>
00007 #include <stdio.h>
00008 #include "stdafx.h"
00009 #include "blockingsocket.h"
00010 
00011 
00012 // Class CBlockingSocket
00013 
00014 void CBlockingSocket::Cleanup()
00015 {
00016         // doesn't throw an exception because it's called in a catch block
00017         if(m_hSocket == NULL) return;
00018         closesocket(m_hSocket);
00019         m_hSocket = NULL;
00020 }
00021 
00022 void CBlockingSocket::Create(int nType /* = SOCK_STREAM */)
00023 {
00024         ASSERT(m_hSocket == NULL);
00025         if((m_hSocket = socket(AF_INET, nType, 0)) == INVALID_SOCKET) 
00026         {
00027                 throw "Create";
00028         }
00029 }
00030 
00031 void CBlockingSocket::Bind(LPCSOCKADDR psa)
00032 {
00033         ASSERT(m_hSocket != NULL);
00034         if(bind(m_hSocket, psa, sizeof(SOCKADDR)) == SOCKET_ERROR) 
00035         {
00036                 throw "Bind";
00037         }
00038 }
00039 
00040 void CBlockingSocket::Listen()
00041 {
00042         ASSERT(m_hSocket != NULL);
00043         if(listen(m_hSocket, 5) == SOCKET_ERROR) 
00044         {
00045                 throw "Listen";
00046         }
00047 }
00048 
00049 bool CBlockingSocket::Accept(CBlockingSocket& sConnect, LPSOCKADDR psa)
00050 {
00051         ASSERT(m_hSocket != NULL);
00052         ASSERT(sConnect.m_hSocket == NULL);
00053         int nLengthAddr = sizeof(SOCKADDR);
00054         sConnect.m_hSocket = accept(m_hSocket, psa, &nLengthAddr);
00055         if(sConnect == INVALID_SOCKET) 
00056         {
00057                 // no exception if the listen was canceled
00058                 if(WSAGetLastError() != WSAEINTR) 
00059                 {
00060                         throw "Accept";
00061                 }
00062                 return FALSE;
00063         }
00064         return TRUE;
00065 }
00066 
00067 void CBlockingSocket::Close()
00068 {
00069         ASSERT(m_hSocket != NULL);
00070         if(closesocket(m_hSocket) == SOCKET_ERROR) 
00071         {
00072                 // should be OK to close if closed already
00073                 throw "Close";
00074         }
00075         m_hSocket = NULL;
00076 }
00077 
00078 void CBlockingSocket::Connect(LPCSOCKADDR psa)
00079 {
00080         ASSERT(m_hSocket != NULL);
00081         // should timeout by itself
00082         if(connect(m_hSocket, psa, sizeof(SOCKADDR)) == SOCKET_ERROR) 
00083         {
00084                 throw "Connect";
00085         }
00086 }
00087 
00088 int CBlockingSocket::Write(const char* pch, const int nSize, const int nSecs)
00089 {
00090         int nBytesSent = 0;
00091         int nBytesThisTime;
00092         const char* pch1 = pch;
00093         do
00094         {
00095                 nBytesThisTime = Send(pch1, nSize - nBytesSent, nSecs);
00096                 nBytesSent += nBytesThisTime;
00097                 pch1 += nBytesThisTime;
00098         } while(nBytesSent < nSize);
00099         return nBytesSent;
00100 }
00101 
00102 int CBlockingSocket::Send(const char* pch, const int nSize, const int nSecs)
00103 {
00104         ASSERT(m_hSocket != NULL);
00105         // returned value will be less than nSize if client cancels the reading
00106         FD_SET fd = {1, m_hSocket};
00107         TIMEVAL tv = {nSecs, 0};
00108         if(select(0, NULL, &fd, NULL, &tv) == 0) 
00109         {
00110                 throw "Send timeout";
00111         }
00112         int nBytesSent;
00113         if((nBytesSent = send(m_hSocket, pch, nSize, 0)) == SOCKET_ERROR) 
00114         {
00115                 throw "Send";
00116         }
00117         return nBytesSent;
00118 }
00119 
00120 int CBlockingSocket::Receive(char* pch, const int nSize, const int nSecs)
00121 {
00122         ASSERT(m_hSocket != NULL);
00123         FD_SET fd = {1, m_hSocket};
00124         TIMEVAL tv = {nSecs, 0};
00125         if(select(0, &fd, NULL, NULL, &tv) == 0) 
00126         {
00127                 throw "Receive timeout";
00128         }
00129 
00130         int nBytesReceived;
00131         if((nBytesReceived = recv(m_hSocket, pch, nSize, 0)) == SOCKET_ERROR) 
00132         {
00133                 throw "Receive";
00134         }
00135         return nBytesReceived;
00136 }
00137 
00138 int CBlockingSocket::ReceiveDatagram(char* pch, const int nSize, LPSOCKADDR psa, const int nSecs)
00139 {
00140         ASSERT(m_hSocket != NULL);
00141         FD_SET fd = {1, m_hSocket};
00142         TIMEVAL tv = {nSecs, 0};
00143         if(select(0, &fd, NULL, NULL, &tv) == 0) 
00144         {
00145                 throw "Receive timeout";
00146         }
00147 
00148         // input buffer should be big enough for the entire datagram
00149         int nFromSize = sizeof(SOCKADDR);
00150         int nBytesReceived = recvfrom(m_hSocket, pch, nSize, 0, psa, &nFromSize);
00151         if(nBytesReceived == SOCKET_ERROR) 
00152         {
00153                 throw "ReceiveDatagram";
00154         }
00155         return nBytesReceived;
00156 }
00157 
00158 int CBlockingSocket::SendDatagram(const char* pch, const int nSize, LPCSOCKADDR psa, const int nSecs)
00159 {
00160         ASSERT(m_hSocket != NULL);
00161         FD_SET fd = {1, m_hSocket};
00162         TIMEVAL tv = {nSecs, 0};
00163         if(select(0, NULL, &fd, NULL, &tv) == 0) 
00164         {
00165                 throw "Send timeout";
00166         }
00167 
00168         int nBytesSent = sendto(m_hSocket, pch, nSize, 0, psa, sizeof(SOCKADDR));
00169         if(nBytesSent == SOCKET_ERROR) 
00170         {
00171                 throw "SendDatagram";
00172         }
00173         return nBytesSent;
00174 }
00175 
00176 void CBlockingSocket::GetPeerAddr(LPSOCKADDR psa)
00177 {
00178         ASSERT(m_hSocket != NULL);
00179         // gets the address of the socket at the other end
00180         int nLengthAddr = sizeof(SOCKADDR);
00181         if(getpeername(m_hSocket, psa, &nLengthAddr) == SOCKET_ERROR) 
00182         {
00183                 throw "GetPeerName";
00184         }
00185 }
00186 
00187 void CBlockingSocket::GetSockAddr(LPSOCKADDR psa)
00188 {
00189         ASSERT(m_hSocket != NULL);
00190         // gets the address of the socket at this end
00191         int nLengthAddr = sizeof(SOCKADDR);
00192         if(getsockname(m_hSocket, psa, &nLengthAddr) == SOCKET_ERROR) 
00193         {
00194                 throw "GetSockName";
00195         }
00196 }
00197 
00198 //static
00199 CSockAddr CBlockingSocket::GetHostByName(const char* pchName, const USHORT ushPort /* = 0 */)
00200 {
00201         hostent* pHostEnt = gethostbyname(pchName);
00202         if(pHostEnt == NULL) 
00203         {
00204                 throw "GetHostByName";
00205         }
00206         ULONG* pulAddr = (ULONG*) pHostEnt->h_addr_list[0];
00207         SOCKADDR_IN sockTemp;
00208         sockTemp.sin_family = AF_INET;
00209         sockTemp.sin_port = htons(ushPort);
00210         sockTemp.sin_addr.s_addr = *pulAddr; // address is already in network byte order
00211         return sockTemp;
00212 }
00213 
00214 //static
00215 const char* CBlockingSocket::GetHostByAddr(LPCSOCKADDR psa)
00216 {
00217         hostent* pHostEnt = gethostbyaddr((char*) &((LPSOCKADDR_IN) psa)->sin_addr.s_addr, 4, PF_INET);
00218         if(pHostEnt == NULL) 
00219         {
00220                 throw "GetHostByAddr";
00221         }
00222         return pHostEnt->h_name; // caller shouldn't delete this memory
00223 }
00224 
00225 CTelnetSocket::CTelnetSocket()
00226 {
00227         m_pReadBuf   = new char[nSizeRecv];
00228         m_nReadBuf   = 0;
00229         m_wFlags     = 0;
00230         m_pLoginName = NULL;
00231 }
00232 
00233 CTelnetSocket::~CTelnetSocket()
00234 {
00235         delete [] m_pReadBuf;
00236         if(m_pLoginName) delete [] m_pLoginName;
00237 }
00238 
00239 bool CTelnetSocket::SetLoginName(const char* pname)
00240 {
00241         m_pLoginName=(char*)malloc(strlen(pname)+1);
00242         if(!m_pLoginName)
00243                 return false;
00244 
00245         strcpy(m_pLoginName,pname);
00246         m_pLoginName[strlen(pname)]='\0';
00247         return true;
00248 }
00249 
00250 int CTelnetSocket::ReadLine(char* pch, const int nSize, const int nSecs)
00251 // reads an entire header line through CRLF (or socket close)
00252 // inserts zero string terminator, object maintains a buffer
00253 {
00254         int nBytesThisTime = m_nReadBuf;
00255         int nLineLength = 0;
00256         char* pch1 = m_pReadBuf;
00257         char* pch2;
00258         do 
00259         {
00260                 // look for lf (assume preceded by cr)
00261                 if((pch2 = (char*) memchr(pch1 , '\n', nBytesThisTime)) != NULL) 
00262                 {
00263                         ASSERT((pch2) > m_pReadBuf);
00264                         ASSERT(*(pch2 - 1) == '\r');
00265                         nLineLength = (pch2 - m_pReadBuf) + 1;
00266                         if(nLineLength >= nSize) nLineLength = nSize - 1;
00267                         memcpy(pch, m_pReadBuf, nLineLength); // copy the line to caller
00268                         m_nReadBuf -= nLineLength;
00269                         memmove(m_pReadBuf, pch2 + 1, m_nReadBuf); // shift remaining characters left
00270                         break;
00271                 }
00272                 pch1 += nBytesThisTime;
00273                 nBytesThisTime = Receive(m_pReadBuf + m_nReadBuf, nSizeRecv - m_nReadBuf, nSecs);
00274                 if(nBytesThisTime <= 0)
00275                 { // sender closed socket or line longer than buffer
00276                         throw "ReadHeaderLine";
00277                 }
00278                 
00279                 //update telnet session
00280                 try 
00281                 {
00282                 //      Write(m_pReadBuf + m_nReadBuf,nBytesThisTime);
00283                 }
00284                 catch(const char* e) 
00285                 {
00286                         e=e;
00287                         throw "ReadHeaderLine::write";
00288                 }
00289                 
00290                 m_nReadBuf += nBytesThisTime;
00291         }
00292         while(TRUE);
00293         *(pch + nLineLength-2) = '\0';  //add rest of buffer, and remove lfcr
00294         return nLineLength;
00295 }
00296 
00297 int CTelnetSocket::ReadResponse(char* pch, const int nSize, const int nSecs)
00298 // reads remainder of a transmission through buffer full or socket close
00299 // (assume headers have been read already)
00300 {
00301         int nBytesToRead, nBytesThisTime, nBytesRead = 0;
00302         if(m_nReadBuf > 0) 
00303         { // copy anything already in the recv buffer
00304                 memcpy(pch, m_pReadBuf, m_nReadBuf);
00305                 pch += m_nReadBuf;
00306                 nBytesRead = m_nReadBuf;
00307                 m_nReadBuf = 0;
00308         }
00309         do 
00310         { // now pass the rest of the data directly to the caller
00311                 nBytesToRead = min(nSizeRecv, nSize - nBytesRead);
00312                 nBytesThisTime = Receive(pch, nBytesToRead, nSecs);
00313                 if(nBytesThisTime <= 0) break; // sender closed the socket
00314                 pch += nBytesThisTime;
00315                 nBytesRead += nBytesThisTime;
00316         }
00317         while(nBytesRead <= nSize);
00318         return nBytesRead;
00319 }
00320 
00321 int CTelnetSocket::Print(const char* msg)
00322 {
00323         int iBytes;
00324         char* buf=(char*)malloc(strlen(msg)+3);
00325         sprintf(buf,"%s\r\n",msg);
00326         iBytes=Write(buf,strlen(buf));
00327         free(buf);
00328         return iBytes;
00329 }

Generated on Mon May 8 22:27:08 2006 by  doxygen 1.3.9.1