1. wxFTP works (somehow)
2. wxSocket/GSocket wxBase support for Unix git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@6738 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
@@ -15,6 +15,7 @@ File hierarchy:
|
|||||||
|
|
||||||
wxBase:
|
wxBase:
|
||||||
|
|
||||||
|
- wxSocket support
|
||||||
- wxDateTime replaces and extends old wxDate and wxTime classes (still
|
- wxDateTime replaces and extends old wxDate and wxTime classes (still
|
||||||
available but strongly deprecated) with many new features
|
available but strongly deprecated) with many new features
|
||||||
- wxLongLong class provides support for (signed) 64 bit integers
|
- wxLongLong class provides support for (signed) 64 bit integers
|
||||||
|
@@ -121,11 +121,11 @@ to specify a user and a password.
|
|||||||
% ----------------------------------------------------------------------------
|
% ----------------------------------------------------------------------------
|
||||||
\membersection{wxFTP::GetList}
|
\membersection{wxFTP::GetList}
|
||||||
|
|
||||||
\func{wxList *}{GetList}{\param{const wxString\&}{ wildcard}}
|
\func{bool}{GetList}{\param{wxArrayString\& }{files}, \param{const wxString\&}{ wildcard = ""}}
|
||||||
|
|
||||||
The GetList function is quite low-level. It returns the list of the files in
|
The GetList function is quite low-level. It returns the list of the files in
|
||||||
the current directory. The list can be filtered using the {\it wildcard} string.
|
the current directory. The list can be filtered using the {\it wildcard} string.
|
||||||
If {\it wildcard} is a NULL string, it will return all files in directory.
|
If {\it wildcard} is empty (default), it will return all files in directory.
|
||||||
|
|
||||||
The form of the list can change from one peer system to another. For example,
|
The form of the list can change from one peer system to another. For example,
|
||||||
for a UNIX peer system, it will look like this:
|
for a UNIX peer system, it will look like this:
|
||||||
@@ -146,7 +146,8 @@ winamp~1 exe 520196 02-25-1999 19:28 winamp204.exe
|
|||||||
1 file(s) 520 196 bytes
|
1 file(s) 520 196 bytes
|
||||||
\end{verbatim}
|
\end{verbatim}
|
||||||
|
|
||||||
The list is a string list and one node corresponds to a line sent by the peer.
|
Return value: TRUE if the file list was successfully retrieved, FALSE
|
||||||
|
otherwise.
|
||||||
|
|
||||||
% ----------------------------------------------------------------------------
|
% ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
@@ -8,6 +8,7 @@
|
|||||||
// Copyright: (c) 1997, 1998 Guilhem Lavaux
|
// Copyright: (c) 1997, 1998 Guilhem Lavaux
|
||||||
// Licence: wxWindows license
|
// Licence: wxWindows license
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#ifndef __WX_FTP_H__
|
#ifndef __WX_FTP_H__
|
||||||
#define __WX_FTP_H__
|
#define __WX_FTP_H__
|
||||||
|
|
||||||
@@ -20,28 +21,23 @@
|
|||||||
#include "wx/protocol/protocol.h"
|
#include "wx/protocol/protocol.h"
|
||||||
#include "wx/url.h"
|
#include "wx/url.h"
|
||||||
|
|
||||||
class WXDLLEXPORT wxFTP : public wxProtocol {
|
class WXDLLEXPORT wxFTP : public wxProtocol
|
||||||
DECLARE_DYNAMIC_CLASS(wxFTP)
|
{
|
||||||
DECLARE_PROTOCOL(wxFTP)
|
|
||||||
public:
|
public:
|
||||||
typedef enum { ASCII, BINARY } wxFTPmode;
|
typedef enum { ASCII, BINARY } wxFTPmode;
|
||||||
|
|
||||||
wxFTP();
|
wxFTP();
|
||||||
~wxFTP();
|
virtual ~wxFTP();
|
||||||
|
|
||||||
bool Close();
|
|
||||||
bool Connect(wxSockAddress& addr, bool wait = TRUE);
|
bool Connect(wxSockAddress& addr, bool wait = TRUE);
|
||||||
bool Connect(const wxString& host);
|
bool Connect(const wxString& host);
|
||||||
|
|
||||||
|
// [forcibly] close the connection
|
||||||
|
bool Close(bool force = FALSE);
|
||||||
|
|
||||||
void SetUser(const wxString& user) { m_user = user; }
|
void SetUser(const wxString& user) { m_user = user; }
|
||||||
void SetPassword(const wxString& passwd) { m_passwd = passwd; }
|
void SetPassword(const wxString& passwd) { m_passwd = passwd; }
|
||||||
|
|
||||||
// Low-level methods
|
|
||||||
bool SendCommand(const wxString& command, char exp_ret);
|
|
||||||
inline virtual wxProtocolError GetError()
|
|
||||||
{ return m_lastError; }
|
|
||||||
const wxString& GetLastResult(); // Get the complete return
|
|
||||||
|
|
||||||
// Filesystem commands
|
// Filesystem commands
|
||||||
bool ChDir(const wxString& dir);
|
bool ChDir(const wxString& dir);
|
||||||
bool MkDir(const wxString& dir);
|
bool MkDir(const wxString& dir);
|
||||||
@@ -56,6 +52,14 @@ public:
|
|||||||
wxOutputStream *GetOutputStream(const wxString& path);
|
wxOutputStream *GetOutputStream(const wxString& path);
|
||||||
|
|
||||||
// List method
|
// List method
|
||||||
|
bool GetList(wxArrayString& files, const wxString& wildcard = wxEmptyString);
|
||||||
|
|
||||||
|
// Low-level methods
|
||||||
|
bool SendCommand(const wxString& command, char exp_ret);
|
||||||
|
virtual wxProtocolError GetError() { return m_lastError; }
|
||||||
|
const wxString& GetLastResult(); // Get the complete return
|
||||||
|
|
||||||
|
// deprecated
|
||||||
wxList *GetList(const wxString& wildcard);
|
wxList *GetList(const wxString& wildcard);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
@@ -69,6 +73,9 @@ protected:
|
|||||||
|
|
||||||
wxSocketClient *GetPort();
|
wxSocketClient *GetPort();
|
||||||
bool GetResult(char exp);
|
bool GetResult(char exp);
|
||||||
|
|
||||||
|
DECLARE_DYNAMIC_CLASS(wxFTP)
|
||||||
|
DECLARE_PROTOCOL(wxFTP)
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif // __WX_FTP_H__
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
/////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
// Name: protocol.h
|
// Name: wx/protocol/protocol.h
|
||||||
// Purpose: Protocol base class
|
// Purpose: Protocol base class
|
||||||
// Author: Guilhem Lavaux
|
// Author: Guilhem Lavaux
|
||||||
// Modified by:
|
// Modified by:
|
||||||
@@ -8,6 +8,7 @@
|
|||||||
// Copyright: (c) 1997, 1998 Guilhem Lavaux
|
// Copyright: (c) 1997, 1998 Guilhem Lavaux
|
||||||
// Licence: wxWindows license
|
// Licence: wxWindows license
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#ifndef _WX_PROTOCOL_PROTOCOL_H
|
#ifndef _WX_PROTOCOL_PROTOCOL_H
|
||||||
#define _WX_PROTOCOL_PROTOCOL_H
|
#define _WX_PROTOCOL_PROTOCOL_H
|
||||||
|
|
||||||
@@ -17,16 +18,20 @@
|
|||||||
|
|
||||||
#include "wx/defs.h"
|
#include "wx/defs.h"
|
||||||
|
|
||||||
|
|
||||||
#include "wx/object.h"
|
#include "wx/object.h"
|
||||||
#include "wx/string.h"
|
#include "wx/string.h"
|
||||||
#include "wx/stream.h"
|
#include "wx/stream.h"
|
||||||
|
|
||||||
#if wxUSE_SOCKETS
|
#if wxUSE_SOCKETS
|
||||||
#include "wx/socket.h"
|
#include "wx/socket.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef enum {
|
// ----------------------------------------------------------------------------
|
||||||
|
// constants
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
wxPROTO_NOERR = 0,
|
wxPROTO_NOERR = 0,
|
||||||
wxPROTO_NETERR,
|
wxPROTO_NETERR,
|
||||||
wxPROTO_PROTERR,
|
wxPROTO_PROTERR,
|
||||||
@@ -39,7 +44,53 @@ typedef enum {
|
|||||||
wxPROTO_STREAMING
|
wxPROTO_STREAMING
|
||||||
} wxProtocolError;
|
} wxProtocolError;
|
||||||
|
|
||||||
// For protocols
|
// ----------------------------------------------------------------------------
|
||||||
|
// wxProtocol: abstract base class for all protocols
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
class WXDLLEXPORT wxProtocol
|
||||||
|
#if wxUSE_SOCKETS
|
||||||
|
: public wxSocketClient
|
||||||
|
#else
|
||||||
|
: public wxObject
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
wxProtocol();
|
||||||
|
|
||||||
|
#if wxUSE_SOCKETS
|
||||||
|
bool Reconnect();
|
||||||
|
virtual bool Connect( const wxString& WXUNUSED(host) ) { return FALSE; }
|
||||||
|
virtual bool Connect( wxSockAddress& addr, bool WXUNUSED(wait) = TRUE) { return wxSocketClient::Connect(addr); }
|
||||||
|
|
||||||
|
// read a '\r\n' terminated line from the given socket and put it in
|
||||||
|
// result (without the terminators)
|
||||||
|
static wxProtocolError ReadLine(wxSocketBase *socket, wxString& result);
|
||||||
|
|
||||||
|
// read a line from this socket - this one can be overridden in the
|
||||||
|
// derived classes if different line termination convention is to be used
|
||||||
|
virtual wxProtocolError ReadLine(wxString& result);
|
||||||
|
#endif // wxUSE_SOCKETS
|
||||||
|
|
||||||
|
virtual bool Abort() = 0;
|
||||||
|
virtual wxInputStream *GetInputStream(const wxString& path) = 0;
|
||||||
|
virtual wxProtocolError GetError() = 0;
|
||||||
|
virtual wxString GetContentType() { return wxEmptyString; }
|
||||||
|
virtual void SetUser(const wxString& WXUNUSED(user)) {}
|
||||||
|
virtual void SetPassword(const wxString& WXUNUSED(passwd) ) {}
|
||||||
|
|
||||||
|
private:
|
||||||
|
DECLARE_ABSTRACT_CLASS(wxProtocol)
|
||||||
|
};
|
||||||
|
|
||||||
|
#if wxUSE_SOCKETS
|
||||||
|
wxProtocolError WXDLLEXPORT GetLine(wxSocketBase *sock, wxString& result);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// macros for protocol classes
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
#define DECLARE_PROTOCOL(class) \
|
#define DECLARE_PROTOCOL(class) \
|
||||||
public: \
|
public: \
|
||||||
static wxProtoInfo g_proto_##class;
|
static wxProtoInfo g_proto_##class;
|
||||||
@@ -47,8 +98,14 @@ public: \
|
|||||||
#define IMPLEMENT_PROTOCOL(class, name, serv, host) \
|
#define IMPLEMENT_PROTOCOL(class, name, serv, host) \
|
||||||
wxProtoInfo class::g_proto_##class(name, serv, host, CLASSINFO(class));
|
wxProtoInfo class::g_proto_##class(name, serv, host, CLASSINFO(class));
|
||||||
|
|
||||||
class WXDLLEXPORT wxProtoInfo : public wxObject {
|
class WXDLLEXPORT wxProtoInfo : public wxObject
|
||||||
DECLARE_DYNAMIC_CLASS(wxProtoInfo)
|
{
|
||||||
|
public:
|
||||||
|
wxProtoInfo(const wxChar *name,
|
||||||
|
const wxChar *serv_name,
|
||||||
|
const bool need_host1,
|
||||||
|
wxClassInfo *info);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
wxProtoInfo *next;
|
wxProtoInfo *next;
|
||||||
wxString m_protoname;
|
wxString m_protoname;
|
||||||
@@ -58,37 +115,8 @@ protected:
|
|||||||
bool m_needhost;
|
bool m_needhost;
|
||||||
|
|
||||||
friend class wxURL;
|
friend class wxURL;
|
||||||
public:
|
|
||||||
wxProtoInfo(const wxChar *name, const wxChar *serv_name, const bool need_host1,
|
DECLARE_DYNAMIC_CLASS(wxProtoInfo)
|
||||||
wxClassInfo *info);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class WXDLLEXPORT wxProtocol
|
|
||||||
#if wxUSE_SOCKETS
|
|
||||||
: public wxSocketClient {
|
|
||||||
#else
|
|
||||||
: public wxObject {
|
|
||||||
#endif
|
|
||||||
DECLARE_ABSTRACT_CLASS(wxProtocol)
|
|
||||||
public:
|
|
||||||
wxProtocol();
|
|
||||||
|
|
||||||
#if wxUSE_SOCKETS
|
|
||||||
bool Reconnect();
|
|
||||||
virtual bool Connect( const wxString& WXUNUSED(host) ) { return FALSE; }
|
|
||||||
virtual bool Connect( wxSockAddress& addr, bool WXUNUSED(wait) = TRUE) { return wxSocketClient::Connect(addr); }
|
|
||||||
#endif
|
|
||||||
|
|
||||||
virtual bool Abort() = 0;
|
|
||||||
virtual wxInputStream *GetInputStream(const wxString& path) = 0;
|
|
||||||
virtual wxProtocolError GetError() = 0;
|
|
||||||
virtual wxString GetContentType() { return wxEmptyString; }
|
|
||||||
virtual void SetUser(const wxString& WXUNUSED(user)) {}
|
|
||||||
virtual void SetPassword(const wxString& WXUNUSED(passwd) ) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
#if wxUSE_SOCKETS
|
|
||||||
wxProtocolError WXDLLEXPORT GetLine(wxSocketBase *sock, wxString& result);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif // _WX_PROTOCOL_PROTOCOL_H
|
#endif // _WX_PROTOCOL_PROTOCOL_H
|
||||||
|
@@ -45,15 +45,34 @@
|
|||||||
//#define TEST_LOG
|
//#define TEST_LOG
|
||||||
//#define TEST_LONGLONG
|
//#define TEST_LONGLONG
|
||||||
//#define TEST_MIME
|
//#define TEST_MIME
|
||||||
//#define TEST_SOCKETS
|
#define TEST_SOCKETS
|
||||||
//#define TEST_STRINGS
|
//#define TEST_STRINGS
|
||||||
//#define TEST_THREADS
|
//#define TEST_THREADS
|
||||||
#define TEST_TIMER
|
//#define TEST_TIMER
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
// implementation
|
// implementation
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// helper functions
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#if defined(TEST_STRINGS) || defined(TEST_SOCKETS)
|
||||||
|
|
||||||
|
// replace TABs with \t and CRs with \n
|
||||||
|
static wxString MakePrintable(const wxChar *s)
|
||||||
|
{
|
||||||
|
wxString str(s);
|
||||||
|
(void)str.Replace(_T("\t"), _T("\\t"));
|
||||||
|
(void)str.Replace(_T("\n"), _T("\\n"));
|
||||||
|
(void)str.Replace(_T("\r"), _T("\\r"));
|
||||||
|
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // MakePrintable() is used
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// wxCmdLineParser
|
// wxCmdLineParser
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
@@ -696,27 +715,129 @@ static void TestBitOperations()
|
|||||||
#ifdef TEST_SOCKETS
|
#ifdef TEST_SOCKETS
|
||||||
|
|
||||||
#include <wx/socket.h>
|
#include <wx/socket.h>
|
||||||
|
#include <wx/protocol/protocol.h>
|
||||||
|
#include <wx/protocol/ftp.h>
|
||||||
|
#include <wx/protocol/http.h>
|
||||||
|
|
||||||
|
static void TestSocketServer()
|
||||||
|
{
|
||||||
|
puts("*** Testing wxSocketServer ***\n");
|
||||||
|
|
||||||
|
// we want to launch a server
|
||||||
|
wxIPV4address addr;
|
||||||
|
addr.Service(3000);
|
||||||
|
|
||||||
|
wxSocketServer *server = new wxSocketServer(addr);
|
||||||
|
if ( !server->Ok() )
|
||||||
|
{
|
||||||
|
puts("ERROR: failed to bind");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void TestSocketClient()
|
static void TestSocketClient()
|
||||||
{
|
{
|
||||||
puts("*** Testing wxSocketClient ***\n");
|
puts("*** Testing wxSocketClient ***\n");
|
||||||
|
|
||||||
wxIPV4address addrDst;
|
static const char *hostname = "www.wxwindows.org";
|
||||||
addrDst.Hostname("www.wxwindows.org");
|
|
||||||
addrDst.Service(80);
|
wxIPV4address addr;
|
||||||
|
addr.Hostname(hostname);
|
||||||
|
addr.Service(80);
|
||||||
|
|
||||||
|
printf("--- Attempting to connect to %s:80...\n", hostname);
|
||||||
|
|
||||||
wxSocketClient client;
|
wxSocketClient client;
|
||||||
if ( !client.Connect(addrDst) )
|
if ( !client.Connect(addr) )
|
||||||
{
|
{
|
||||||
printf("ERROR: failed to connect to %s\n", addrDst.Hostname().c_str());
|
printf("ERROR: failed to connect to %s\n", hostname);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
printf("--- Connected to %s:%u...\n",
|
||||||
|
addr.Hostname().c_str(), addr.Service());
|
||||||
|
|
||||||
char buf[8192];
|
char buf[8192];
|
||||||
|
|
||||||
client.Write("get /front.htm\n", 17);
|
// could use simply "GET" here I suppose
|
||||||
|
wxString cmdGet =
|
||||||
|
wxString::Format("GET http://%s/\r\n", hostname);
|
||||||
|
client.Write(cmdGet, cmdGet.length());
|
||||||
|
printf("--- Sent command '%s' to the server\n",
|
||||||
|
MakePrintable(cmdGet).c_str());
|
||||||
client.Read(buf, WXSIZEOF(buf));
|
client.Read(buf, WXSIZEOF(buf));
|
||||||
printf("Server replied:\n%s", buf);
|
printf("--- Server replied:\n%s", buf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void TestProtocolFtp()
|
||||||
|
{
|
||||||
|
puts("*** Testing wxFTP ***\n");
|
||||||
|
|
||||||
|
wxLog::AddTraceMask(_T("ftp"));
|
||||||
|
|
||||||
|
static const char *hostname = "ftp.wxwindows.org";
|
||||||
|
|
||||||
|
printf("--- Attempting to connect to %s:21...\n", hostname);
|
||||||
|
|
||||||
|
wxFTP ftp;
|
||||||
|
if ( !ftp.Connect(hostname) )
|
||||||
|
{
|
||||||
|
printf("ERROR: failed to connect to %s\n", hostname);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf("--- Connected to %s, current directory is '%s'\n",
|
||||||
|
hostname, ftp.Pwd().c_str());
|
||||||
|
if ( !ftp.ChDir(_T("pub")) )
|
||||||
|
{
|
||||||
|
puts("ERROR: failed to cd to pub");
|
||||||
|
}
|
||||||
|
|
||||||
|
wxArrayString files;
|
||||||
|
if ( !ftp.GetList(files) )
|
||||||
|
{
|
||||||
|
puts("ERROR: failed to get list of files");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf("List of files under '%s':\n", ftp.Pwd().c_str());
|
||||||
|
size_t count = files.GetCount();
|
||||||
|
for ( size_t n = 0; n < count; n++ )
|
||||||
|
{
|
||||||
|
printf("\t%s\n", files[n].c_str());
|
||||||
|
}
|
||||||
|
puts("End of the file list");
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( !ftp.ChDir(_T("..")) )
|
||||||
|
{
|
||||||
|
puts("ERROR: failed to cd to ..");
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char *filename = "welcome.msg";
|
||||||
|
wxInputStream *in = ftp.GetInputStream(filename);
|
||||||
|
if ( !in )
|
||||||
|
{
|
||||||
|
puts("ERROR: couldn't get input stream");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
size_t size = in->StreamSize();
|
||||||
|
printf("Reading file %s (%u bytes)...", filename, size);
|
||||||
|
|
||||||
|
char *data = new char[size];
|
||||||
|
if ( !in->Read(data, size) )
|
||||||
|
{
|
||||||
|
puts("ERROR: read error");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf("\nContents of %s:\n%s\n", filename, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
delete [] data;
|
||||||
|
delete in;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2139,17 +2260,6 @@ static void TestStringFind()
|
|||||||
puts("");
|
puts("");
|
||||||
}
|
}
|
||||||
|
|
||||||
// replace TABs with \t and CRs with \n
|
|
||||||
static wxString MakePrintable(const wxChar *s)
|
|
||||||
{
|
|
||||||
wxString str(s);
|
|
||||||
(void)str.Replace(_T("\t"), _T("\\t"));
|
|
||||||
(void)str.Replace(_T("\n"), _T("\\n"));
|
|
||||||
(void)str.Replace(_T("\r"), _T("\\r"));
|
|
||||||
|
|
||||||
return str;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void TestStringTokenizer()
|
static void TestStringTokenizer()
|
||||||
{
|
{
|
||||||
puts("*** Testing wxStringTokenizer ***");
|
puts("*** Testing wxStringTokenizer ***");
|
||||||
@@ -2443,7 +2553,12 @@ int main(int argc, char **argv)
|
|||||||
#endif // TEST_MIME
|
#endif // TEST_MIME
|
||||||
|
|
||||||
#ifdef TEST_SOCKETS
|
#ifdef TEST_SOCKETS
|
||||||
|
if ( 0 )
|
||||||
|
{
|
||||||
|
TestSocketServer();
|
||||||
TestSocketClient();
|
TestSocketClient();
|
||||||
|
}
|
||||||
|
TestProtocolFtp();
|
||||||
#endif // TEST_SOCKETS
|
#endif // TEST_SOCKETS
|
||||||
|
|
||||||
#ifdef TEST_TIMER
|
#ifdef TEST_TIMER
|
||||||
|
@@ -38,11 +38,15 @@
|
|||||||
#include "wx/sckstrm.h"
|
#include "wx/sckstrm.h"
|
||||||
#include "wx/protocol/protocol.h"
|
#include "wx/protocol/protocol.h"
|
||||||
#include "wx/protocol/ftp.h"
|
#include "wx/protocol/ftp.h"
|
||||||
|
#include "wx/log.h"
|
||||||
|
|
||||||
#ifdef __BORLANDC__
|
#ifdef __BORLANDC__
|
||||||
#pragma hdrstop
|
#pragma hdrstop
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// the length of FTP status code (3 digits)
|
||||||
|
static const size_t LEN_CODE = 3;
|
||||||
|
|
||||||
#define FTP_BSIZE 1024
|
#define FTP_BSIZE 1024
|
||||||
|
|
||||||
IMPLEMENT_DYNAMIC_CLASS(wxFTP, wxProtocol)
|
IMPLEMENT_DYNAMIC_CLASS(wxFTP, wxProtocol)
|
||||||
@@ -59,9 +63,7 @@ wxFTP::wxFTP()
|
|||||||
m_streaming = FALSE;
|
m_streaming = FALSE;
|
||||||
|
|
||||||
m_user = wxT("anonymous");
|
m_user = wxT("anonymous");
|
||||||
m_passwd = wxGetUserId();
|
m_passwd << wxGetUserId() << wxT('@') << wxGetFullHostName();
|
||||||
m_passwd += wxT('@');
|
|
||||||
m_passwd += wxGetHostName();
|
|
||||||
|
|
||||||
SetNotify(0);
|
SetNotify(0);
|
||||||
SetFlags(wxSOCKET_NONE);
|
SetFlags(wxSOCKET_NONE);
|
||||||
@@ -69,7 +71,7 @@ wxFTP::wxFTP()
|
|||||||
|
|
||||||
wxFTP::~wxFTP()
|
wxFTP::~wxFTP()
|
||||||
{
|
{
|
||||||
SendCommand("QUIT", '2');
|
Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////
|
||||||
@@ -120,59 +122,159 @@ bool wxFTP::Connect(const wxString& host)
|
|||||||
return Connect(addr);
|
return Connect(addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool wxFTP::Close()
|
bool wxFTP::Close(bool force)
|
||||||
{
|
{
|
||||||
if (m_streaming) {
|
if ( m_streaming )
|
||||||
|
{
|
||||||
|
if ( !force )
|
||||||
|
{
|
||||||
m_lastError = wxPROTO_STREAMING;
|
m_lastError = wxPROTO_STREAMING;
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
if (IsConnected())
|
|
||||||
SendCommand(wxString(wxT("QUIT")), '2');
|
(void)Abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( IsConnected() )
|
||||||
|
SendCommand(wxT("QUIT"), '2');
|
||||||
|
|
||||||
return wxSocketClient::Close();
|
return wxSocketClient::Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////
|
// ============================================================================
|
||||||
////// wxFTP low-level methods /////////////////////////////////
|
// low level methods
|
||||||
////////////////////////////////////////////////////////////////
|
// ============================================================================
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// Send command to FTP server
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
bool wxFTP::SendCommand(const wxString& command, char exp_ret)
|
bool wxFTP::SendCommand(const wxString& command, char exp_ret)
|
||||||
{
|
{
|
||||||
wxString tmp_str;
|
wxString tmp_str;
|
||||||
|
|
||||||
if (m_streaming) {
|
if (m_streaming)
|
||||||
|
{
|
||||||
m_lastError = wxPROTO_STREAMING;
|
m_lastError = wxPROTO_STREAMING;
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
tmp_str = command + wxT("\r\n");
|
tmp_str = command + wxT("\r\n");
|
||||||
const wxWX2MBbuf tmp_buf = tmp_str.mb_str();
|
const wxWX2MBbuf tmp_buf = tmp_str.mb_str();
|
||||||
if (Write(wxMBSTRINGCAST tmp_buf, strlen(tmp_buf)).Error()) {
|
if ( Write(wxMBSTRINGCAST tmp_buf, strlen(tmp_buf)).Error())
|
||||||
|
{
|
||||||
m_lastError = wxPROTO_NETERR;
|
m_lastError = wxPROTO_NETERR;
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
wxLogTrace(_T("ftp"), _T("==> %s"), command.c_str());
|
||||||
|
|
||||||
return GetResult(exp_ret);
|
return GetResult(exp_ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// Recieve servers reply
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
bool wxFTP::GetResult(char exp)
|
bool wxFTP::GetResult(char exp)
|
||||||
{
|
{
|
||||||
m_lastError = GetLine(this, m_lastResult);
|
wxString code;
|
||||||
|
|
||||||
|
// we handle multiline replies here according to RFC 959: it says that a
|
||||||
|
// reply may either be on 1 line of the form "xyz ..." or on several lines
|
||||||
|
// in whuch case it looks like
|
||||||
|
// xyz-...
|
||||||
|
// ...
|
||||||
|
// xyz ...
|
||||||
|
// and the intermeidate lines may start with xyz or not
|
||||||
|
bool badReply = FALSE;
|
||||||
|
bool firstLine = TRUE;
|
||||||
|
bool endOfReply = FALSE;
|
||||||
|
while ( !endOfReply && !badReply )
|
||||||
|
{
|
||||||
|
m_lastError = ReadLine(m_lastResult);
|
||||||
if ( m_lastError )
|
if ( m_lastError )
|
||||||
return FALSE;
|
return FALSE;
|
||||||
if (m_lastResult.GetChar(0) != exp) {
|
|
||||||
|
// unless this is an intermediate line of a multiline reply, it must
|
||||||
|
// contain the code in the beginning and '-' or ' ' following it
|
||||||
|
if ( m_lastResult.Len() < LEN_CODE + 1 )
|
||||||
|
{
|
||||||
|
if ( firstLine )
|
||||||
|
{
|
||||||
|
badReply = TRUE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
wxLogTrace(_T("ftp"), _T("<== %s %s"),
|
||||||
|
code.c_str(), m_lastResult.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else // line has at least 4 chars
|
||||||
|
{
|
||||||
|
// this is the char which tells us what we're dealing with
|
||||||
|
wxChar chMarker = m_lastResult.GetChar(LEN_CODE);
|
||||||
|
|
||||||
|
if ( firstLine )
|
||||||
|
{
|
||||||
|
code = wxString(m_lastResult, LEN_CODE);
|
||||||
|
wxLogTrace(_T("ftp"), _T("<== %s %s"),
|
||||||
|
code.c_str(), m_lastResult.c_str() + LEN_CODE + 1);
|
||||||
|
|
||||||
|
switch ( chMarker )
|
||||||
|
{
|
||||||
|
case _T(' '):
|
||||||
|
endOfReply = TRUE;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case _T('-'):
|
||||||
|
firstLine = FALSE;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
// unexpected
|
||||||
|
badReply = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else // subsequent line of multiline reply
|
||||||
|
{
|
||||||
|
if ( wxStrncmp(m_lastResult, code, LEN_CODE) == 0 )
|
||||||
|
{
|
||||||
|
if ( chMarker == _T(' ') )
|
||||||
|
{
|
||||||
|
endOfReply = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
wxLogTrace(_T("ftp"), _T("<== %s %s"),
|
||||||
|
code.c_str(), m_lastResult.c_str() + LEN_CODE + 1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// just part of reply
|
||||||
|
wxLogTrace(_T("ftp"), _T("<== %s %s"),
|
||||||
|
code.c_str(), m_lastResult.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( badReply )
|
||||||
|
{
|
||||||
|
wxLogDebug(_T("Broken FTP server: '%s' is not a valid reply."),
|
||||||
|
m_lastResult.c_str());
|
||||||
|
|
||||||
m_lastError = wxPROTO_PROTERR;
|
m_lastError = wxPROTO_PROTERR;
|
||||||
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_lastResult.GetChar(3) == '-') {
|
if ( code.GetChar(0) != exp )
|
||||||
wxString key = m_lastResult.Left((size_t)3);
|
{
|
||||||
|
m_lastError = wxPROTO_PROTERR;
|
||||||
|
|
||||||
key += wxT(' ');
|
|
||||||
|
|
||||||
while (m_lastResult.Index(key) != 0) {
|
|
||||||
m_lastError = GetLine(this, m_lastResult);
|
|
||||||
if ( m_lastError )
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -204,15 +306,45 @@ bool wxFTP::RmDir(const wxString& dir)
|
|||||||
|
|
||||||
wxString wxFTP::Pwd()
|
wxString wxFTP::Pwd()
|
||||||
{
|
{
|
||||||
int beg, end;
|
wxString path;
|
||||||
|
|
||||||
if (!SendCommand(wxT("PWD"), '2'))
|
if ( SendCommand(wxT("PWD"), '2') )
|
||||||
return wxString((char *)NULL);
|
{
|
||||||
|
// the result is at least that long if SendCommand() succeeded
|
||||||
|
const wxChar *p = m_lastResult.c_str() + LEN_CODE + 1;
|
||||||
|
if ( *p != _T('"') )
|
||||||
|
{
|
||||||
|
wxLogDebug(_T("Missing starting quote in reply for PWD: %s"), p);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for ( p++; *p; p++ )
|
||||||
|
{
|
||||||
|
if ( *p == _T('"') )
|
||||||
|
{
|
||||||
|
// check if the quote is doubled
|
||||||
|
p++;
|
||||||
|
if ( !*p || *p != _T('"') )
|
||||||
|
{
|
||||||
|
// no, this is the end
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
//else: yes, it is: this is an embedded quote in the
|
||||||
|
// filename, treat as normal char
|
||||||
|
}
|
||||||
|
|
||||||
beg = m_lastResult.Find(wxT('\"'),FALSE);
|
path += *p;
|
||||||
end = m_lastResult.Find(wxT('\"'),TRUE);
|
}
|
||||||
|
|
||||||
return wxString(beg+1, end);
|
if ( !*p )
|
||||||
|
{
|
||||||
|
wxLogDebug(_T("Missing ending quote in reply for PWD: %s"),
|
||||||
|
m_lastResult.c_str() + LEN_CODE + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool wxFTP::Rename(const wxString& src, const wxString& dst)
|
bool wxFTP::Rename(const wxString& src, const wxString& dst)
|
||||||
@@ -312,11 +444,15 @@ wxSocketClient *wxFTP::GetPort()
|
|||||||
return client;
|
return client;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool wxFTP::Abort(void)
|
bool wxFTP::Abort()
|
||||||
{
|
{
|
||||||
|
if ( !m_streaming )
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
m_streaming = FALSE;
|
m_streaming = FALSE;
|
||||||
if (!SendCommand(wxT("ABOR"), '4'))
|
if ( !SendCommand(wxT("ABOR"), '4') )
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
return GetResult('2');
|
return GetResult('2');
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -369,6 +505,42 @@ wxOutputStream *wxFTP::GetOutputStream(const wxString& path)
|
|||||||
return new wxOutputFTPStream(this, sock);
|
return new wxOutputFTPStream(this, sock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool wxFTP::GetList(wxArrayString& files, const wxString& wildcard)
|
||||||
|
{
|
||||||
|
wxSocketBase *sock = GetPort();
|
||||||
|
if ( !sock )
|
||||||
|
{
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
wxString line = _T("NLST");
|
||||||
|
if ( !!wildcard )
|
||||||
|
{
|
||||||
|
// notice that there is no space here
|
||||||
|
line += wildcard;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( !SendCommand(line, '1') )
|
||||||
|
{
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
files.Empty();
|
||||||
|
|
||||||
|
while ( ReadLine(sock, line) == wxPROTO_NOERR )
|
||||||
|
{
|
||||||
|
files.Add(line);
|
||||||
|
}
|
||||||
|
|
||||||
|
delete sock;
|
||||||
|
|
||||||
|
// the file list should be terminated by "226 Transfer complete""
|
||||||
|
if ( !GetResult('2') )
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
wxList *wxFTP::GetList(const wxString& wildcard)
|
wxList *wxFTP::GetList(const wxString& wildcard)
|
||||||
{
|
{
|
||||||
wxList *file_list = new wxList;
|
wxList *file_list = new wxList;
|
||||||
|
@@ -82,6 +82,56 @@ bool wxProtocol::Reconnect()
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// Read a line from socket
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// TODO ReadLine() should use buffers private to wxProtocol for efficiency!
|
||||||
|
|
||||||
|
// static
|
||||||
|
wxProtocolError wxProtocol::ReadLine(wxSocketBase *socket, wxString& result)
|
||||||
|
{
|
||||||
|
result.Empty();
|
||||||
|
char ch, chLast = '\0';
|
||||||
|
while ( !socket->Read(&ch, sizeof(ch)).Error() )
|
||||||
|
{
|
||||||
|
switch ( ch )
|
||||||
|
{
|
||||||
|
case '\r':
|
||||||
|
// remember it, if the following is '\n', we're done
|
||||||
|
chLast = '\r';
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '\n':
|
||||||
|
// only ends line if the previous character was '\r'
|
||||||
|
if ( chLast == '\r' )
|
||||||
|
{
|
||||||
|
// EOL found
|
||||||
|
return wxPROTO_NOERR;
|
||||||
|
}
|
||||||
|
//else: fall through
|
||||||
|
|
||||||
|
default:
|
||||||
|
// normal char
|
||||||
|
if ( chLast )
|
||||||
|
{
|
||||||
|
result += chLast;
|
||||||
|
chLast = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
result += ch;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return wxPROTO_NETERR;
|
||||||
|
}
|
||||||
|
|
||||||
|
wxProtocolError wxProtocol::ReadLine(wxString& result)
|
||||||
|
{
|
||||||
|
return ReadLine(this, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
// old function which only chops '\n' and not '\r\n'
|
||||||
wxProtocolError GetLine(wxSocketBase *sock, wxString& result) {
|
wxProtocolError GetLine(wxSocketBase *sock, wxString& result) {
|
||||||
#define PROTO_BSIZE 2048
|
#define PROTO_BSIZE 2048
|
||||||
size_t avail, size;
|
size_t avail, size;
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
# This file was automatically generated by tmake at 15:55, 2000/03/14
|
# This file was automatically generated by tmake at 09:19, 2000/03/15
|
||||||
# DO NOT CHANGE THIS FILE, YOUR CHANGES WILL BE LOST! CHANGE BASE.T!
|
# DO NOT CHANGE THIS FILE, YOUR CHANGES WILL BE LOST! CHANGE BASE.T!
|
||||||
ALL_SOURCES = \
|
ALL_SOURCES = \
|
||||||
common/init.cpp \
|
common/init.cpp \
|
||||||
@@ -19,7 +19,9 @@ ALL_SOURCES = \
|
|||||||
common/fs_inet.cpp \
|
common/fs_inet.cpp \
|
||||||
common/fs_mem.cpp \
|
common/fs_mem.cpp \
|
||||||
common/fs_zip.cpp \
|
common/fs_zip.cpp \
|
||||||
|
common/ftp.cpp \
|
||||||
common/hash.cpp \
|
common/hash.cpp \
|
||||||
|
common/http.cpp \
|
||||||
common/intl.cpp \
|
common/intl.cpp \
|
||||||
common/list.cpp \
|
common/list.cpp \
|
||||||
common/log.cpp \
|
common/log.cpp \
|
||||||
@@ -30,7 +32,13 @@ ALL_SOURCES = \
|
|||||||
common/object.cpp \
|
common/object.cpp \
|
||||||
common/objstrm.cpp \
|
common/objstrm.cpp \
|
||||||
common/process.cpp \
|
common/process.cpp \
|
||||||
|
common/protocol.cpp \
|
||||||
|
common/sckaddr.cpp \
|
||||||
|
common/sckfile.cpp \
|
||||||
|
common/sckipc.cpp \
|
||||||
|
common/sckstrm.cpp \
|
||||||
common/serbase.cpp \
|
common/serbase.cpp \
|
||||||
|
common/socket.cpp \
|
||||||
common/strconv.cpp \
|
common/strconv.cpp \
|
||||||
common/stream.cpp \
|
common/stream.cpp \
|
||||||
common/string.cpp \
|
common/string.cpp \
|
||||||
@@ -39,6 +47,7 @@ ALL_SOURCES = \
|
|||||||
common/tokenzr.cpp \
|
common/tokenzr.cpp \
|
||||||
common/txtstrm.cpp \
|
common/txtstrm.cpp \
|
||||||
common/unzip.c \
|
common/unzip.c \
|
||||||
|
common/url.cpp \
|
||||||
common/utilscmn.cpp \
|
common/utilscmn.cpp \
|
||||||
common/variant.cpp \
|
common/variant.cpp \
|
||||||
common/wfstream.cpp \
|
common/wfstream.cpp \
|
||||||
@@ -118,6 +127,8 @@ ALL_HEADERS = \
|
|||||||
protocol/protocol.h
|
protocol/protocol.h
|
||||||
|
|
||||||
BASE_OBJS = \
|
BASE_OBJS = \
|
||||||
|
ipcbase.o \
|
||||||
|
gsocket.o \
|
||||||
init.o \
|
init.o \
|
||||||
appcmn.o \
|
appcmn.o \
|
||||||
cmdline.o \
|
cmdline.o \
|
||||||
@@ -136,7 +147,9 @@ BASE_OBJS = \
|
|||||||
fs_inet.o \
|
fs_inet.o \
|
||||||
fs_mem.o \
|
fs_mem.o \
|
||||||
fs_zip.o \
|
fs_zip.o \
|
||||||
|
ftp.o \
|
||||||
hash.o \
|
hash.o \
|
||||||
|
http.o \
|
||||||
intl.o \
|
intl.o \
|
||||||
list.o \
|
list.o \
|
||||||
log.o \
|
log.o \
|
||||||
@@ -147,7 +160,13 @@ BASE_OBJS = \
|
|||||||
object.o \
|
object.o \
|
||||||
objstrm.o \
|
objstrm.o \
|
||||||
process.o \
|
process.o \
|
||||||
|
protocol.o \
|
||||||
|
sckaddr.o \
|
||||||
|
sckfile.o \
|
||||||
|
sckipc.o \
|
||||||
|
sckstrm.o \
|
||||||
serbase.o \
|
serbase.o \
|
||||||
|
socket.o \
|
||||||
strconv.o \
|
strconv.o \
|
||||||
stream.o \
|
stream.o \
|
||||||
string.o \
|
string.o \
|
||||||
@@ -156,6 +175,7 @@ BASE_OBJS = \
|
|||||||
tokenzr.o \
|
tokenzr.o \
|
||||||
txtstrm.o \
|
txtstrm.o \
|
||||||
unzip.o \
|
unzip.o \
|
||||||
|
url.o \
|
||||||
utilscmn.o \
|
utilscmn.o \
|
||||||
variant.o \
|
variant.o \
|
||||||
wfstream.o \
|
wfstream.o \
|
||||||
@@ -182,7 +202,9 @@ BASE_DEPS = \
|
|||||||
fs_inet.d \
|
fs_inet.d \
|
||||||
fs_mem.d \
|
fs_mem.d \
|
||||||
fs_zip.d \
|
fs_zip.d \
|
||||||
|
ftp.d \
|
||||||
hash.d \
|
hash.d \
|
||||||
|
http.d \
|
||||||
intl.d \
|
intl.d \
|
||||||
list.d \
|
list.d \
|
||||||
log.d \
|
log.d \
|
||||||
@@ -193,7 +215,13 @@ BASE_DEPS = \
|
|||||||
object.d \
|
object.d \
|
||||||
objstrm.d \
|
objstrm.d \
|
||||||
process.d \
|
process.d \
|
||||||
|
protocol.d \
|
||||||
|
sckaddr.d \
|
||||||
|
sckfile.d \
|
||||||
|
sckipc.d \
|
||||||
|
sckstrm.d \
|
||||||
serbase.d \
|
serbase.d \
|
||||||
|
socket.d \
|
||||||
strconv.d \
|
strconv.d \
|
||||||
stream.d \
|
stream.d \
|
||||||
string.d \
|
string.d \
|
||||||
@@ -202,6 +230,7 @@ BASE_DEPS = \
|
|||||||
tokenzr.d \
|
tokenzr.d \
|
||||||
txtstrm.d \
|
txtstrm.d \
|
||||||
unzip.d \
|
unzip.d \
|
||||||
|
url.d \
|
||||||
utilscmn.d \
|
utilscmn.d \
|
||||||
variant.d \
|
variant.d \
|
||||||
wfstream.d \
|
wfstream.d \
|
||||||
@@ -234,7 +263,9 @@ BASE_DEPS = \
|
|||||||
fs_inet.d \
|
fs_inet.d \
|
||||||
fs_mem.d \
|
fs_mem.d \
|
||||||
fs_zip.d \
|
fs_zip.d \
|
||||||
|
ftp.d \
|
||||||
hash.d \
|
hash.d \
|
||||||
|
http.d \
|
||||||
intl.d \
|
intl.d \
|
||||||
list.d \
|
list.d \
|
||||||
log.d \
|
log.d \
|
||||||
@@ -245,7 +276,13 @@ BASE_DEPS = \
|
|||||||
object.d \
|
object.d \
|
||||||
objstrm.d \
|
objstrm.d \
|
||||||
process.d \
|
process.d \
|
||||||
|
protocol.d \
|
||||||
|
sckaddr.d \
|
||||||
|
sckfile.d \
|
||||||
|
sckipc.d \
|
||||||
|
sckstrm.d \
|
||||||
serbase.d \
|
serbase.d \
|
||||||
|
socket.d \
|
||||||
strconv.d \
|
strconv.d \
|
||||||
stream.d \
|
stream.d \
|
||||||
string.d \
|
string.d \
|
||||||
@@ -254,6 +291,7 @@ BASE_DEPS = \
|
|||||||
tokenzr.d \
|
tokenzr.d \
|
||||||
txtstrm.d \
|
txtstrm.d \
|
||||||
unzip.d \
|
unzip.d \
|
||||||
|
url.d \
|
||||||
utilscmn.d \
|
utilscmn.d \
|
||||||
variant.d \
|
variant.d \
|
||||||
wfstream.d \
|
wfstream.d \
|
||||||
|
@@ -90,27 +90,30 @@ struct sockaddr_un {
|
|||||||
|
|
||||||
|
|
||||||
#ifndef __GSOCKET_STANDALONE__
|
#ifndef __GSOCKET_STANDALONE__
|
||||||
|
# include "wx/unix/gsockunx.h"
|
||||||
#include "wx/unix/gsockunx.h"
|
# include "wx/gsocket.h"
|
||||||
#include "wx/gsocket.h"
|
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
# include "gsockunx.h"
|
||||||
#include "gsockunx.h"
|
# include "gsocket.h"
|
||||||
#include "gsocket.h"
|
|
||||||
|
|
||||||
#endif /* __GSOCKET_STANDALONE__ */
|
#endif /* __GSOCKET_STANDALONE__ */
|
||||||
|
|
||||||
/* redefine some GUI-only functions to do nothing in console mode */
|
/* redefine some GUI-only functions to do nothing in console mode */
|
||||||
#if defined(wxUSE_GUI) && !wxUSE_GUI
|
#if defined(wxUSE_GUI) && !wxUSE_GUI
|
||||||
#define _GSocket_GUI_Init(socket)
|
# define _GSocket_GUI_Init(socket) (1)
|
||||||
#define _GSocket_GUI_Destroy(socket)
|
# define _GSocket_GUI_Destroy(socket)
|
||||||
#define _GSocket_Enable_Events(socket)
|
# define _GSocket_Enable_Events(socket)
|
||||||
#define _GSocket_Disable_Events(socket)
|
# define _GSocket_Disable_Events(socket)
|
||||||
#define _GSocket_Install_Callback(socket, event)
|
# define _GSocket_Install_Callback(socket, event)
|
||||||
#define _GSocket_Uninstall_Callback(socket, event)
|
# define _GSocket_Uninstall_Callback(socket, event)
|
||||||
#endif /* wxUSE_GUI */
|
#endif /* wxUSE_GUI */
|
||||||
|
|
||||||
|
/* debugging helpers */
|
||||||
|
#ifdef __GSOCKET_DEBUG__
|
||||||
|
#define GSocket_Debug(args) printf args
|
||||||
|
#else
|
||||||
|
#define GSocket_Debug(args)
|
||||||
|
#endif // __GSOCKET_DEBUG__
|
||||||
|
|
||||||
/* Global initialisers */
|
/* Global initialisers */
|
||||||
|
|
||||||
bool GSocket_Init(void)
|
bool GSocket_Init(void)
|
||||||
@@ -126,7 +129,7 @@ void GSocket_Cleanup(void)
|
|||||||
|
|
||||||
GSocket *GSocket_new(void)
|
GSocket *GSocket_new(void)
|
||||||
{
|
{
|
||||||
int i;
|
int i, success;
|
||||||
GSocket *socket;
|
GSocket *socket;
|
||||||
|
|
||||||
socket = (GSocket *)malloc(sizeof(GSocket));
|
socket = (GSocket *)malloc(sizeof(GSocket));
|
||||||
@@ -152,7 +155,8 @@ GSocket *GSocket_new(void)
|
|||||||
socket->m_establishing = FALSE;
|
socket->m_establishing = FALSE;
|
||||||
|
|
||||||
/* Per-socket GUI-specific initialization */
|
/* Per-socket GUI-specific initialization */
|
||||||
if (!_GSocket_GUI_Init(socket))
|
success = _GSocket_GUI_Init(socket);
|
||||||
|
if (!success)
|
||||||
{
|
{
|
||||||
free(socket);
|
free(socket);
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -719,7 +723,7 @@ int GSocket_Write(GSocket *socket, const char *buffer, int size)
|
|||||||
|
|
||||||
assert(socket != NULL);
|
assert(socket != NULL);
|
||||||
|
|
||||||
printf( "GSocket_Write #1, size %d\n", size );
|
GSocket_Debug(( "GSocket_Write #1, size %d\n", size ));
|
||||||
|
|
||||||
if (socket->m_fd == -1 || socket->m_server)
|
if (socket->m_fd == -1 || socket->m_server)
|
||||||
{
|
{
|
||||||
@@ -727,13 +731,13 @@ int GSocket_Write(GSocket *socket, const char *buffer, int size)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
printf( "GSocket_Write #2, size %d\n", size );
|
GSocket_Debug(( "GSocket_Write #2, size %d\n", size ));
|
||||||
|
|
||||||
/* If the socket is blocking, wait for writability (with a timeout) */
|
/* If the socket is blocking, wait for writability (with a timeout) */
|
||||||
if (_GSocket_Output_Timeout(socket) == GSOCK_TIMEDOUT)
|
if (_GSocket_Output_Timeout(socket) == GSOCK_TIMEDOUT)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
printf( "GSocket_Write #3, size %d\n", size );
|
GSocket_Debug(( "GSocket_Write #3, size %d\n", size ));
|
||||||
|
|
||||||
/* Write the data */
|
/* Write the data */
|
||||||
if (socket->m_stream)
|
if (socket->m_stream)
|
||||||
@@ -741,19 +745,19 @@ int GSocket_Write(GSocket *socket, const char *buffer, int size)
|
|||||||
else
|
else
|
||||||
ret = _GSocket_Send_Dgram(socket, buffer, size);
|
ret = _GSocket_Send_Dgram(socket, buffer, size);
|
||||||
|
|
||||||
printf( "GSocket_Write #4, size %d\n", size );
|
GSocket_Debug(( "GSocket_Write #4, size %d\n", size ));
|
||||||
|
|
||||||
if (ret == -1)
|
if (ret == -1)
|
||||||
{
|
{
|
||||||
if (errno == EWOULDBLOCK)
|
if (errno == EWOULDBLOCK)
|
||||||
{
|
{
|
||||||
socket->m_error = GSOCK_WOULDBLOCK;
|
socket->m_error = GSOCK_WOULDBLOCK;
|
||||||
printf( "GSocket_Write error WOULDBLOCK\n" );
|
GSocket_Debug(( "GSocket_Write error WOULDBLOCK\n" ));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
socket->m_error = GSOCK_IOERR;
|
socket->m_error = GSOCK_IOERR;
|
||||||
printf( "GSocket_Write error IOERR\n" );
|
GSocket_Debug(( "GSocket_Write error IOERR\n" ));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Only reenable OUTPUT events after an error (just like WSAAsyncSelect
|
/* Only reenable OUTPUT events after an error (just like WSAAsyncSelect
|
||||||
@@ -765,7 +769,7 @@ int GSocket_Write(GSocket *socket, const char *buffer, int size)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
printf( "GSocket_Write #5, size %d ret %d\n", size, ret );
|
GSocket_Debug(( "GSocket_Write #5, size %d ret %d\n", size, ret ));
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@@ -779,9 +783,104 @@ int GSocket_Write(GSocket *socket, const char *buffer, int size)
|
|||||||
*/
|
*/
|
||||||
GSocketEventFlags GSocket_Select(GSocket *socket, GSocketEventFlags flags)
|
GSocketEventFlags GSocket_Select(GSocket *socket, GSocketEventFlags flags)
|
||||||
{
|
{
|
||||||
|
#if defined(wxUSE_GUI) && !wxUSE_GUI
|
||||||
|
|
||||||
|
GSocketEventFlags result = 0;
|
||||||
|
fd_set readfds;
|
||||||
|
fd_set writefds;
|
||||||
|
fd_set exceptfds;
|
||||||
|
struct timeval tv;
|
||||||
|
|
||||||
|
/* Do not use a static struct, Linux can garble it */
|
||||||
|
tv.tv_sec = 0;
|
||||||
|
tv.tv_usec = 0;
|
||||||
|
|
||||||
assert(socket != NULL);
|
assert(socket != NULL);
|
||||||
|
|
||||||
|
FD_ZERO(&readfds);
|
||||||
|
FD_ZERO(&writefds);
|
||||||
|
FD_ZERO(&exceptfds);
|
||||||
|
FD_SET(socket->m_fd, &readfds);
|
||||||
|
FD_SET(socket->m_fd, &writefds);
|
||||||
|
FD_SET(socket->m_fd, &exceptfds);
|
||||||
|
|
||||||
|
/* Check known state first */
|
||||||
|
result |= (GSOCK_CONNECTION_FLAG & socket->m_detected & flags);
|
||||||
|
result |= (GSOCK_LOST_FLAG & socket->m_detected & flags);
|
||||||
|
|
||||||
|
/* Try select now */
|
||||||
|
if (select(socket->m_fd + 1, &readfds, &writefds, &exceptfds, &tv) <= 0)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
/* Check for readability */
|
||||||
|
if (FD_ISSET(socket->m_fd, &readfds))
|
||||||
|
{
|
||||||
|
char c;
|
||||||
|
|
||||||
|
if (recv(socket->m_fd, &c, 1, MSG_PEEK) > 0)
|
||||||
|
{
|
||||||
|
result |= (GSOCK_INPUT_FLAG & flags);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (socket->m_server && socket->m_stream)
|
||||||
|
{
|
||||||
|
result |= (GSOCK_CONNECTION_FLAG & flags);
|
||||||
|
socket->m_detected |= GSOCK_CONNECTION_FLAG;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result |= (GSOCK_LOST_FLAG & flags);
|
||||||
|
socket->m_detected = GSOCK_LOST_FLAG;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check for writability */
|
||||||
|
if (FD_ISSET(socket->m_fd, &writefds))
|
||||||
|
{
|
||||||
|
if (socket->m_establishing && !socket->m_server)
|
||||||
|
{
|
||||||
|
int error;
|
||||||
|
SOCKLEN_T len = sizeof(error);
|
||||||
|
|
||||||
|
socket->m_establishing = FALSE;
|
||||||
|
|
||||||
|
getsockopt(socket->m_fd, SOL_SOCKET, SO_ERROR, (void*)&error, &len);
|
||||||
|
|
||||||
|
if (error)
|
||||||
|
{
|
||||||
|
result |= (GSOCK_LOST_FLAG & flags);
|
||||||
|
socket->m_detected = GSOCK_LOST_FLAG;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result |= (GSOCK_CONNECTION_FLAG & flags);
|
||||||
|
socket->m_detected |= GSOCK_CONNECTION_FLAG;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result |= (GSOCK_OUTPUT_FLAG & flags);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check for exceptions and errors (is this useful in Unices?) */
|
||||||
|
if (FD_ISSET(socket->m_fd, &exceptfds))
|
||||||
|
{
|
||||||
|
result |= (GSOCK_LOST_FLAG & flags);
|
||||||
|
socket->m_establishing = FALSE;
|
||||||
|
socket->m_detected = GSOCK_LOST_FLAG;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
assert(socket != NULL);
|
||||||
return flags & socket->m_detected;
|
return flags & socket->m_detected;
|
||||||
|
|
||||||
|
#endif /* !wxUSE_GUI */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Flags */
|
/* Flags */
|
||||||
@@ -928,17 +1027,17 @@ GSocketError _GSocket_Input_Timeout(GSocket *socket)
|
|||||||
ret = select(socket->m_fd + 1, &readfds, NULL, NULL, &tv);
|
ret = select(socket->m_fd + 1, &readfds, NULL, NULL, &tv);
|
||||||
if (ret == 0)
|
if (ret == 0)
|
||||||
{
|
{
|
||||||
printf( "GSocket_Input_Timeout, select returned 0\n" );
|
GSocket_Debug(( "GSocket_Input_Timeout, select returned 0\n" ));
|
||||||
socket->m_error = GSOCK_TIMEDOUT;
|
socket->m_error = GSOCK_TIMEDOUT;
|
||||||
return GSOCK_TIMEDOUT;
|
return GSOCK_TIMEDOUT;
|
||||||
}
|
}
|
||||||
if (ret == -1)
|
if (ret == -1)
|
||||||
{
|
{
|
||||||
printf( "GSocket_Input_Timeout, select returned -1\n" );
|
GSocket_Debug(( "GSocket_Input_Timeout, select returned -1\n" ));
|
||||||
if (errno == EBADF) printf( "Invalid file descriptor\n" );
|
if (errno == EBADF) GSocket_Debug(( "Invalid file descriptor\n" ));
|
||||||
if (errno == EINTR) printf( "A non blocked signal was caught\n" );
|
if (errno == EINTR) GSocket_Debug(( "A non blocked signal was caught\n" ));
|
||||||
if (errno == EINVAL) printf( "The highest number descriptor is negative\n" );
|
if (errno == EINVAL) GSocket_Debug(( "The highest number descriptor is negative\n" ));
|
||||||
if (errno == ENOMEM) printf( "Not enough memory\n" );
|
if (errno == ENOMEM) GSocket_Debug(( "Not enough memory\n" ));
|
||||||
socket->m_error = GSOCK_TIMEDOUT;
|
socket->m_error = GSOCK_TIMEDOUT;
|
||||||
return GSOCK_TIMEDOUT;
|
return GSOCK_TIMEDOUT;
|
||||||
}
|
}
|
||||||
@@ -967,17 +1066,17 @@ GSocketError _GSocket_Output_Timeout(GSocket *socket)
|
|||||||
ret = select(socket->m_fd + 1, NULL, &writefds, NULL, &tv);
|
ret = select(socket->m_fd + 1, NULL, &writefds, NULL, &tv);
|
||||||
if (ret == 0)
|
if (ret == 0)
|
||||||
{
|
{
|
||||||
printf( "GSocket_Output_Timeout, select returned 0\n" );
|
GSocket_Debug(( "GSocket_Output_Timeout, select returned 0\n" ));
|
||||||
socket->m_error = GSOCK_TIMEDOUT;
|
socket->m_error = GSOCK_TIMEDOUT;
|
||||||
return GSOCK_TIMEDOUT;
|
return GSOCK_TIMEDOUT;
|
||||||
}
|
}
|
||||||
if (ret == -1)
|
if (ret == -1)
|
||||||
{
|
{
|
||||||
printf( "GSocket_Output_Timeout, select returned -1\n" );
|
GSocket_Debug(( "GSocket_Output_Timeout, select returned -1\n" ));
|
||||||
if (errno == EBADF) printf( "Invalid file descriptor\n" );
|
if (errno == EBADF) GSocket_Debug(( "Invalid file descriptor\n" ));
|
||||||
if (errno == EINTR) printf( "A non blocked signal was caught\n" );
|
if (errno == EINTR) GSocket_Debug(( "A non blocked signal was caught\n" ));
|
||||||
if (errno == EINVAL) printf( "The highest number descriptor is negative\n" );
|
if (errno == EINVAL) GSocket_Debug(( "The highest number descriptor is negative\n" ));
|
||||||
if (errno == ENOMEM) printf( "Not enough memory\n" );
|
if (errno == ENOMEM) GSocket_Debug(( "Not enough memory\n" ));
|
||||||
socket->m_error = GSOCK_TIMEDOUT;
|
socket->m_error = GSOCK_TIMEDOUT;
|
||||||
return GSOCK_TIMEDOUT;
|
return GSOCK_TIMEDOUT;
|
||||||
}
|
}
|
||||||
@@ -1069,27 +1168,22 @@ int _GSocket_Send_Dgram(GSocket *socket, const char *buffer, int size)
|
|||||||
void _GSocket_Detected_Read(GSocket *socket)
|
void _GSocket_Detected_Read(GSocket *socket)
|
||||||
{
|
{
|
||||||
char c;
|
char c;
|
||||||
int ret;
|
|
||||||
|
|
||||||
ret = recv(socket->m_fd, &c, 1, MSG_PEEK);
|
if (recv(socket->m_fd, &c, 1, MSG_PEEK) > 0)
|
||||||
|
|
||||||
if (socket->m_stream)
|
|
||||||
{
|
|
||||||
if (ret < 0 && socket->m_server)
|
|
||||||
{
|
|
||||||
CALL_CALLBACK(socket, GSOCK_CONNECTION);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ret > 0)
|
|
||||||
{
|
{
|
||||||
CALL_CALLBACK(socket, GSOCK_INPUT);
|
CALL_CALLBACK(socket, GSOCK_INPUT);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
if (socket->m_server && socket->m_stream)
|
||||||
|
{
|
||||||
|
CALL_CALLBACK(socket, GSOCK_CONNECTION);
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
CALL_CALLBACK(socket, GSOCK_LOST);
|
CALL_CALLBACK(socket, GSOCK_LOST);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void _GSocket_Detected_Write(GSocket *socket)
|
void _GSocket_Detected_Write(GSocket *socket)
|
||||||
@@ -1101,7 +1195,7 @@ void _GSocket_Detected_Write(GSocket *socket)
|
|||||||
|
|
||||||
socket->m_establishing = FALSE;
|
socket->m_establishing = FALSE;
|
||||||
|
|
||||||
getsockopt(socket->m_fd, SOL_SOCKET, SO_ERROR, (void*) &error, &len);
|
getsockopt(socket->m_fd, SOL_SOCKET, SO_ERROR, (void*)&error, &len);
|
||||||
|
|
||||||
if (error)
|
if (error)
|
||||||
{
|
{
|
||||||
|
Reference in New Issue
Block a user