1///////////////////////////////////////////////////////////////////////////// 2// Name: src/common/protocol.cpp 3// Purpose: Implement protocol base class 4// Author: Guilhem Lavaux 5// Modified by: 6// Created: 07/07/1997 7// RCS-ID: $Id: protocol.cpp 40943 2006-08-31 19:31:43Z ABX $ 8// Copyright: (c) 1997, 1998 Guilhem Lavaux 9// Licence: wxWindows licence 10///////////////////////////////////////////////////////////////////////////// 11 12// For compilers that support precompilation, includes "wx.h". 13#include "wx/wxprec.h" 14 15#ifdef __BORLANDC__ 16 #pragma hdrstop 17#endif 18 19#if wxUSE_PROTOCOL 20 21#include "wx/protocol/protocol.h" 22 23#ifndef WX_PRECOMP 24 #include "wx/module.h" 25#endif 26 27#include "wx/url.h" 28 29#include <stdlib.h> 30 31///////////////////////////////////////////////////////////////// 32// wxProtoInfo 33///////////////////////////////////////////////////////////////// 34 35/* 36 * -------------------------------------------------------------- 37 * --------- wxProtoInfo CONSTRUCTOR ---------------------------- 38 * -------------------------------------------------------------- 39 */ 40 41wxProtoInfo::wxProtoInfo(const wxChar *name, const wxChar *serv, 42 const bool need_host1, wxClassInfo *info) 43 : m_protoname(name), 44 m_servname(serv) 45{ 46 m_cinfo = info; 47 m_needhost = need_host1; 48#if wxUSE_URL 49 next = wxURL::ms_protocols; 50 wxURL::ms_protocols = this; 51#else 52 next = NULL; 53#endif 54} 55 56///////////////////////////////////////////////////////////////// 57// wxProtocol /////////////////////////////////////////////////// 58///////////////////////////////////////////////////////////////// 59 60#if wxUSE_SOCKETS 61IMPLEMENT_ABSTRACT_CLASS(wxProtocol, wxSocketClient) 62#else 63IMPLEMENT_ABSTRACT_CLASS(wxProtocol, wxObject) 64#endif 65 66wxProtocol::wxProtocol() 67#if wxUSE_SOCKETS 68 : wxSocketClient() 69#endif 70{ 71} 72 73#if wxUSE_SOCKETS 74bool wxProtocol::Reconnect() 75{ 76 wxIPV4address addr; 77 78 if (!GetPeer(addr)) 79 { 80 Close(); 81 return false; 82 } 83 84 if (!Close()) 85 return false; 86 87 if (!Connect(addr)) 88 return false; 89 90 return true; 91} 92 93// ---------------------------------------------------------------------------- 94// Read a line from socket 95// ---------------------------------------------------------------------------- 96 97/* static */ 98wxProtocolError wxProtocol::ReadLine(wxSocketBase *sock, wxString& result) 99{ 100 static const int LINE_BUF = 4095; 101 102 result.clear(); 103 104 wxCharBuffer buf(LINE_BUF); 105 char *pBuf = buf.data(); 106 while ( sock->WaitForRead() ) 107 { 108 // peek at the socket to see if there is a CRLF 109 sock->Peek(pBuf, LINE_BUF); 110 111 size_t nRead = sock->LastCount(); 112 if ( !nRead && sock->Error() ) 113 return wxPROTO_NETERR; 114 115 // look for "\r\n" paying attention to a special case: "\r\n" could 116 // have been split by buffer boundary, so check also for \r at the end 117 // of the last chunk and \n at the beginning of this one 118 pBuf[nRead] = '\0'; 119 const char *eol = strchr(pBuf, '\n'); 120 121 // if we found '\n', is there a '\r' as well? 122 if ( eol ) 123 { 124 if ( eol == pBuf ) 125 { 126 // check for case of "\r\n" being split 127 if ( result.empty() || result.Last() != _T('\r') ) 128 { 129 // ignore the stray '\n' 130 eol = NULL; 131 } 132 //else: ok, got real EOL 133 134 // read just this '\n' and restart 135 nRead = 1; 136 } 137 else // '\n' in the middle of the buffer 138 { 139 // in any case, read everything up to and including '\n' 140 nRead = eol - pBuf + 1; 141 142 if ( eol[-1] != '\r' ) 143 { 144 // as above, simply ignore stray '\n' 145 eol = NULL; 146 } 147 } 148 } 149 150 sock->Read(pBuf, nRead); 151 if ( sock->LastCount() != nRead ) 152 return wxPROTO_NETERR; 153 154 pBuf[nRead] = '\0'; 155 result += wxString::FromAscii(pBuf); 156 157 if ( eol ) 158 { 159 // remove trailing "\r\n" 160 result.RemoveLast(2); 161 162 return wxPROTO_NOERR; 163 } 164 } 165 166 return wxPROTO_NETERR; 167} 168 169wxProtocolError wxProtocol::ReadLine(wxString& result) 170{ 171 return ReadLine(this, result); 172} 173 174// old function which only chops '\n' and not '\r\n' 175wxProtocolError GetLine(wxSocketBase *sock, wxString& result) 176{ 177#define PROTO_BSIZE 2048 178 size_t avail, size; 179 char tmp_buf[PROTO_BSIZE], tmp_str[PROTO_BSIZE]; 180 char *ret; 181 bool found; 182 183 avail = sock->Read(tmp_buf, PROTO_BSIZE).LastCount(); 184 if (sock->Error() || avail == 0) 185 return wxPROTO_NETERR; 186 187 memcpy(tmp_str, tmp_buf, avail); 188 189 // Not implemented on all systems 190 // ret = (char *)memccpy(tmp_str, tmp_buf, '\n', avail); 191 found = false; 192 for (ret=tmp_str;ret < (tmp_str+avail); ret++) 193 if (*ret == '\n') 194 { 195 found = true; 196 break; 197 } 198 199 if (!found) 200 return wxPROTO_PROTERR; 201 202 *ret = 0; 203 204 result = wxString::FromAscii( tmp_str ); 205 result = result.Left(result.length()-1); 206 207 size = ret-tmp_str+1; 208 sock->Unread(&tmp_buf[size], avail-size); 209 210 return wxPROTO_NOERR; 211#undef PROTO_BSIZE 212} 213#endif // wxUSE_SOCKETS 214 215#endif // wxUSE_PROTOCOL 216