1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /*
3  * Pan - A Newsreader for Gtk+
4  * Copyright (C) 2002-2006  Charles Kerr <charles@rebelbase.com>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; version 2 of the License.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, see <http://www.gnu.org/licenses/>.
17  *
18  */
19 
20 #ifndef __NNTP_Pool_h__
21 #define __NNTP_Pool_h__
22 
23 #include <vector>
24 #include <string>
25 #include <pan/general/quark.h>
26 #include <pan/data/server-info.h>
27 #include <pan/tasks/socket.h>
28 #include <pan/tasks/nntp.h>
29 #include <pan/tasks/socket-impl-main.h>
30 #include <pan/gui/prefs.h>
31 #include <pan/data/data.h>
32 
33 #ifdef HAVE_GNUTLS
34   #include <pan/data/cert-store.h>
35 #endif
36 
37 namespace pan {
38 struct WorkerPool;
39 
40 /**
41  * A pool of NNTP connections to a particular server.
42  *
43  * @ingroup tasks
44  */
45 class NNTP_Pool: public NNTP::Source,
46 		private NNTP::Listener,
47 		private Socket::Creator::Listener,
48 		private CertStore::Listener {
49 public:
50 
51 	NNTP_Pool(const Quark & server, ServerInfo & server_info, Prefs& prefs, SocketCreator *,
52 			CertStore &);
53 	virtual ~NNTP_Pool();
54 
55 	virtual void check_in(NNTP*, Health);
56 	NNTP* check_out();
57 	void abort_tasks();
58 	void kill_tasks();
59 	void idle_upkeep();
60 
61 	void get_counts(int& setme_active, int& setme_idle, int& setme_connecting,
62 			int& setme_max) const;
63 
64 public:
65 
66 	/** Interface class for objects that listen to an NNTP_Pool's events */
67 	class Listener {
68 	public:
~Listener()69 		virtual ~Listener() {
70 		}
71 		;
72 		virtual void on_pool_has_nntp_available(const Quark& server) = 0;
73 		virtual void on_pool_error(const Quark& server,
74 				const StringView& message) = 0;
75 	};
76 
add_listener(Listener * l)77 	void add_listener(Listener * l) {
78 		_listeners.insert(l);
79 	}
remove_listener(Listener * l)80 	void remove_listener(Listener * l) {
81 		_listeners.erase(l);
82 	}
83 	void request_nntp(WorkerPool&);
84 
85 private:
86 	//  NNTP::Listener
87 	virtual void on_nntp_done(NNTP*, Health, const StringView&);
88 
89 private:
90 	// Socket::Creator::Listener
91 	virtual void on_socket_created(const StringView& host, int port, bool ok,	Socket*);
on_socket_shutdown(const StringView & host,int port,Socket *)92 	virtual void on_socket_shutdown(const StringView& host, int port, Socket*) {}
93 #ifdef HAVE_GNUTLS
94 private:
95 	// CertStore::Listener
96 	virtual void on_verify_cert_failed(gnutls_x509_crt_t, std::string, int);
97 	virtual void on_valid_cert_added(gnutls_x509_crt_t, std::string);
98 #endif
99 private:
100 
fire_pool_has_nntp_available()101 	void fire_pool_has_nntp_available() {
102 		for (listeners_t::iterator it(_listeners.begin()),
103 				end(_listeners.end()); it != end;)
104 			(*it++)->on_pool_has_nntp_available(_server);
105 	}
fire_pool_error(const StringView & message)106 	void fire_pool_error(const StringView& message) {
107 		for (listeners_t::iterator it(_listeners.begin()),
108 				end(_listeners.end()); it != end;)
109 			(*it++)->on_pool_error(_server, message);
110 	}
111 
112 	ServerInfo& _server_info;
113 	const Quark _server;
114 	SocketCreator * _socket_creator;
115 	int _pending_connections;
116 	CertStore& _certstore;
117 	Prefs& _prefs;
118 
119 	struct PoolItem {
120 		NNTP * nntp;
121 		bool is_checked_in;
122 		time_t last_active_time;
123 	};
124 	typedef std::vector<PoolItem> pool_items_t;
125 	pool_items_t _pool_items;
126 	int _active_count;
127 
128 private:
129 
130 	time_t _time_to_allow_new_connections;
131 	bool new_connections_are_allowed() const;
132 	void disallow_new_connections_for_n_seconds(int n);
133 	void allow_new_connections();
134 
135 	typedef std::set<Listener*> listeners_t;
136 	listeners_t _listeners;
137 };
138 }
139 ;
140 
141 #endif // __NNTP_Pool_h__
142