1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189
|
/* $Id: fd.H,v 1.2 2004/04/06 02:06:36 mrsam Exp $
**
** Copyright 2002-2004, Double Precision Inc.
**
** See COPYING for distribution information.
*/
#ifndef libmail_fd_H
#define libmail_fd_H
#include "mail.H"
#include <string>
#include <queue>
LIBMAIL_START
///////////////////////////////////////////////////////////////////////////
//
// A network connection-based (optionally encrypted) mail::account handler.
//
// Implements the process() method.
//
// The subclass should invoke socketWrite() to write to the network
// connection. socketWrite() can receive either a string, or a WriteBuffer.
// A WriteBuffer is subclassed to implement writing large amounts of data.
// The subclass must implement WriteBuffer::fillWriteBuffer() to save
// the next portion of data that needs to be written in the writebuffer
// field. WriteBuffer::fillWriteBuffer() gets called repeatedly each time
// the contents of writebuffer are succesfully written out.
// WriteBuffer::fillWriteBuffer() must return false when there's no more
// data to be written out, in which case the objects gets destroyed by
// mail::fd.
//
// The subclass should implement socketRead() to process read information.
// socketRead() receives everything read from the network connection, but
// not processed, and should return the number of characters that were
// processed (0 - need more input, < 0, error)
//
// The subclass should implement disconnect() which gets invoked when the
// network connection is closed.
//
// The remaining public interface is obvious.
class fdTLS;
class fd : public mail::account {
int socketfd;
bool ioDebugFlag;
protected:
bool writtenFlag;
public:
int getfd() { return socketfd; }
class WriteBuffer {
public:
WriteBuffer();
virtual ~WriteBuffer();
std::string writebuffer;
virtual bool fillWriteBuffer();
};
static std::string rootCertRequiredErrMsg;
// Error message returned when SSL certificate verification is
// requested, but trusted SSL certificate authority list is not
// installed.
fd(mail::callback::disconnect &disconnect_callback);
virtual ~fd();
std::string socketDisconnect();
//
// Disconnect the socket. If socketDisconnect() is invoked after
// a fatal network error, a non-empty error message is returned.
std::string socketConnect(class mail::loginInfo &loginInfo,
const char *plainservice,
const char *sslservice);
//
// Create a new server connection, should be called shortly after
// the constructor.
//
// loginInfo - login parameters.
// plainService, sslService - default ports to connect to, for SSL
// and non-SSL connections.
//
// Returns an empty string for success, or an error message.
std::string socketAttach(int fd);
//
// Attach to an existing socket
//
bool socketConnected();
//
// Returns non-zero if a network connection exists (may not necessarily
// be kigged on).
//
virtual void disconnect(const char *reason)=0;
// The subclass must implement the disconnect method. Reason is the
// error message responsible for disconnecting, or a null or an empty
// string for an orderly shut down.
virtual int socketRead(const std::string &readbuffer)=0;
//
// The subclass must implement socketRead() to process read data in
// readbuffer. socketRead should return the number of bytes consumed
// (which may be 0, if socketRead needs to see more data before it
// can be consumed).
void socketWrite(std::string s);
void socketWrite(WriteBuffer *p);
// When TLS is enabled, socketBeginEncryption initiates SSL
// negotiation. The login parameters may already specify that the
// server connection should be encrypted right from the start, in
// which case fd begin SSL negotiation automatically as soon
// as the connection is established. socketEncrypted() may be used
// to determine whether the connection is already encrypted. If not,
// passing a copy of the original login parameters to
// socketBeginEncryption() will begin SSL negotiation.
bool socketBeginEncryption(mail::loginInfo &);
bool socketEncrypted()
{
return tls != NULL;
}
bool socketEndEncryption();
//
// socketEndEncryption() terminates SSL negotiation, which normally
// happens prior to disconnecting from the server.
// socketEndEncryption() returns true if an SSL connection is
// currently active, and SSL disconnection was initiated.
// The disconnect() method will be called automatically after SSL
// terminates. Typical usage:
//
// if (!socketEndEncryption()) socketDisconnect();
protected:
int process(std::vector<pollfd> &fds, int &timeout);
private:
std::string starttls(class mail::loginInfo &loginInfo,
bool starttlsFlag);
public:
static time_t getTimeoutSetting(mail::loginInfo &loginInfo,
const char *name, time_t defaultValue,
time_t minValue, time_t maxValue);
private:
bool establishtls();
int connecting; // Connection in progress
fdTLS *tls; // SSL/TLS stuff
std::queue<WriteBuffer *> writequeue;
// Stuff waiting to be written out
std::string *getWriteBuffer(); // Get next stuff to write
void writtenBuffer(size_t n) // Stubb was written
{
std::string *s= &writequeue.front()->writebuffer;
*s= s->substr(n);
}
std::string readbuffer; // Stuff read, but not processed.
fd(const fd &); // UNDEFINED
fd &operator=(const fd &); // UNDEFINED
};
LIBMAIL_END
#endif
|