summaryrefslogtreecommitdiffstats
path: root/libmail/fd.H
blob: c64036202570adb6e51ae7fc8910788b57744296 (plain)
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
190
191
/*
** Copyright 2002-2008, 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;

	std::vector<std::string> certificates;

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,
	   std::vector<std::string> &certificatesArg);

	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