#ifndef _H_FTP_PROTOCOL
#define _H_FTP_PROTOCOL
#include "xfercore.h"
#include "protocol.h"
#include "transfer.h"
#include "netconnection.h"
#include "neterror.h"
#include <Security/ip++.h>
#include <Security/inetreply.h>
namespace Security {
namespace Network {
class FTPProtocol : public Protocol {
protected:
class FTPConnection;
public:
class FTPTransfer;
static const IPPort defaultFtpPort = 21;
FTPProtocol(Manager &mgr);
public:
FTPTransfer *makeTransfer(const Target &target, Operation operation);
public:
enum {
downloadDirectory = protocolSpecific, downloadListing, makeDirectory, removeDirectory, removeFile, genericCommand };
private:
class FTPDataConnection : public TransferEngine::Client, public TCPClientSocket {
public:
FTPDataConnection(FTPConnection &conn) : connection(conn) { }
FTPConnection &connection;
void start(Sink &sink); void start(Source &source); void close(); void connectionDone();
OSStatus status() const { return mFailureStatus; }
int fileDesc() const;
protected:
void transit(Event event, char *input, size_t inputLength);
void transitError(const CssmCommonError &error);
void setup();
void finish();
private:
OSStatus mFailureStatus; bool mTransferDone; bool mConnectionDone; };
protected:
class FTPConnection : public TCPConnection {
friend class FTPDataConnection;
public:
FTPConnection(Protocol &proto, const HostTarget &tgt);
enum State {
errorState,
loginInitial, loginUserSent, loginPassSent,
idle,
typeCommandSent, passiveSent, portSent, restartSent, transferSent, transferInProgress,
directCommandSent,
START = loginInitial
};
FTPTransfer &transfer() { return transferAs<FTPTransfer>(); }
void request(const char *path);
void abort();
protected:
void transit(Event event, char *input, size_t inputLength);
void transitError(const CssmCommonError &error);
bool validate();
void startCommand(); void startTransfer(bool restarted = false);
bool imageMode() const { return mImageMode; }
void imageMode(bool mode);
void fail(const char *reply, OSStatus error = Transfer::defaultOSStatusError)
{ setError(reply, error); Error::throwMe(error); }
void fail() { retain(false); Connection::fail(); }
protected:
State state; InetReply::Continuation replyContinuation;
bool mImageMode; bool mPassive;
string mOperationPath;
FTPDataConnection mDataPath; TCPServerSocket mReceiver; };
public:
class FTPTransfer : public Transfer {
public:
FTPTransfer(Protocol &proto, const Target &target, Operation operation);
ResultClass resultClass() const;
string &ftpResponse() { return mPrimaryResponseString; }
unsigned int &ftpResponseCode() { return mPrimaryResponseCode; }
unsigned int ftpResponseCode() const { return mPrimaryResponseCode; }
protected:
void start(); void abort();
string mFailedReply;
private:
string mPrimaryResponseString; unsigned int mPrimaryResponseCode; };
private:
struct FTPAddress {
unsigned int h1, h2, h3, h4, p1, p2;
FTPAddress() { }
FTPAddress(const IPSockAddress &addr);
operator IPSockAddress () const;
};
};
} }
#endif //_H_FTP_PROTOCOL