Rename camel_service_get_settings().
[platform/upstream/evolution-data-server.git] / camel / camel-network-service.c
1 /*
2  * camel-network-service.c
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) version 3.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with the program; if not, see <http://www.gnu.org/licenses/>
16  *
17  */
18
19 #include "camel-network-service.h"
20
21 #include <config.h>
22 #include <glib/gi18n-lib.h>
23
24 #include <camel/camel-enumtypes.h>
25 #include <camel/camel-network-settings.h>
26 #include <camel/camel-service.h>
27 #include <camel/camel-session.h>
28 #include <camel/camel-tcp-stream-raw.h>
29
30 #include <camel/camel-tcp-stream-ssl.h>
31
32 G_DEFINE_INTERFACE (
33         CamelNetworkService,
34         camel_network_service,
35         CAMEL_TYPE_SERVICE)
36
37 static CamelStream *
38 network_service_connect_sync (CamelNetworkService *service,
39                               GCancellable *cancellable,
40                               GError **error)
41 {
42         CamelNetworkSecurityMethod method;
43         CamelNetworkSettings *network_settings;
44         CamelSettings *settings;
45         CamelSession *session;
46         CamelStream *stream;
47         const gchar *service_name;
48         guint16 default_port;
49         guint16 port;
50         gchar *socks_host;
51         gint socks_port;
52         gchar *host;
53         gint status;
54
55         session = camel_service_get_session (CAMEL_SERVICE (service));
56         settings = camel_service_ref_settings (CAMEL_SERVICE (service));
57         g_return_val_if_fail (CAMEL_IS_NETWORK_SETTINGS (settings), NULL);
58
59         network_settings = CAMEL_NETWORK_SETTINGS (settings);
60         method = camel_network_settings_get_security_method (network_settings);
61         host = camel_network_settings_dup_host (network_settings);
62         port = camel_network_settings_get_port (network_settings);
63
64         g_object_unref (settings);
65
66         service_name = camel_network_service_get_service_name (service, method);
67         default_port = camel_network_service_get_default_port (service, method);
68
69         /* If the URL explicitly gives a port number, make
70          * it override the service name and default port. */
71         if (port > 0) {
72                 service_name = g_alloca (16);
73                 sprintf ((gchar *) service_name, "%u", port);
74                 default_port = 0;
75         }
76
77         switch (method) {
78                 case CAMEL_NETWORK_SECURITY_METHOD_NONE:
79                         stream = camel_tcp_stream_raw_new ();
80                         break;
81
82                 case CAMEL_NETWORK_SECURITY_METHOD_STARTTLS_ON_STANDARD_PORT:
83                         stream = camel_tcp_stream_ssl_new_raw (
84                                 session, host,
85                                 CAMEL_TCP_STREAM_SSL_ENABLE_TLS);
86                         break;
87
88                 case CAMEL_NETWORK_SECURITY_METHOD_SSL_ON_ALTERNATE_PORT:
89                         stream = camel_tcp_stream_ssl_new (
90                                 session, host,
91                                 CAMEL_TCP_STREAM_SSL_ENABLE_SSL2 |
92                                 CAMEL_TCP_STREAM_SSL_ENABLE_SSL3);
93                         break;
94
95                 default:
96                         g_return_val_if_reached (NULL);
97         }
98
99         camel_session_get_socks_proxy (session, host, &socks_host, &socks_port);
100
101         if (socks_host != NULL) {
102                 camel_tcp_stream_set_socks_proxy (
103                         CAMEL_TCP_STREAM (stream),
104                         socks_host, socks_port);
105                 g_free (socks_host);
106         }
107
108         status = camel_tcp_stream_connect (
109                 CAMEL_TCP_STREAM (stream), host,
110                 service_name, default_port, cancellable, error);
111
112         if (status == -1) {
113                 g_prefix_error (
114                         error, _("Could not connect to %s: "), host);
115                 g_object_unref (stream);
116                 stream = NULL;
117         }
118
119         g_free (host);
120
121         return stream;
122 }
123
124 static void
125 camel_network_service_default_init (CamelNetworkServiceInterface *interface)
126 {
127         interface->connect_sync = network_service_connect_sync;
128 }
129
130 /**
131  * camel_network_service_get_service_name:
132  * @service: a #CamelNetworkService
133  * @method: a #CamelNetworkSecurityMethod
134  *
135  * Returns the standard network service name for @service and the security
136  * method @method, as defined in /etc/services.  For example, the service
137  * name for unencrypted IMAP or encrypted IMAP using STARTTLS is "imap",
138  * but the service name for IMAP over SSL is "imaps".
139  *
140  * Returns: the network service name for @service and @method, or %NULL
141  *
142  * Since: 3.2
143  **/
144 const gchar *
145 camel_network_service_get_service_name (CamelNetworkService *service,
146                                         CamelNetworkSecurityMethod method)
147 {
148         CamelNetworkServiceInterface *interface;
149         const gchar *service_name = NULL;
150
151         g_return_val_if_fail (CAMEL_IS_NETWORK_SERVICE (service), NULL);
152
153         interface = CAMEL_NETWORK_SERVICE_GET_INTERFACE (service);
154
155         if (interface->get_service_name != NULL)
156                 service_name = interface->get_service_name (service, method);
157
158         return service_name;
159 }
160
161 /**
162  * camel_network_service_get_default_port:
163  * @service: a #CamelNetworkService
164  * @method: a #CamelNetworkSecurityMethod
165  *
166  * Returns the default network port number for @service and the security
167  * method @method, as defined in /etc/services.  For example, the default
168  * port for unencrypted IMAP or encrypted IMAP using STARTTLS is 143, but
169  * the default port for IMAP over SSL is 993.
170  *
171  * Returns: the default port number for @service and @method
172  *
173  * Since: 3.2
174  **/
175 guint16
176 camel_network_service_get_default_port (CamelNetworkService *service,
177                                         CamelNetworkSecurityMethod method)
178 {
179         CamelNetworkServiceInterface *interface;
180         guint16 default_port = 0;
181
182         g_return_val_if_fail (CAMEL_IS_NETWORK_SERVICE (service), 0);
183
184         interface = CAMEL_NETWORK_SERVICE_GET_INTERFACE (service);
185
186         if (interface->get_default_port != NULL)
187                 default_port = interface->get_default_port (service, method);
188
189         return default_port;
190 }
191
192 /**
193  * camel_network_service_connect_sync:
194  * @service: a #CamelNetworkService
195  * @cancellable: optional #GCancellable object, or %NULL
196  * @error: return location for a #GError, or %NULL
197  *
198  * Attempts to establish a network connection to the server described by
199  * @service, using the preferred #CamelNetworkSettings:security-method to
200  * secure the connection.  If a connection cannot be established, or the
201  * connection attempt is cancelled, the function sets @error and returns
202  * %NULL.
203  *
204  * Returns: a #CamelStream, or %NULL
205  *
206  * Since: 3.2
207  **/
208 CamelStream *
209 camel_network_service_connect_sync (CamelNetworkService *service,
210                                     GCancellable *cancellable,
211                                     GError **error)
212 {
213         CamelNetworkServiceInterface *interface;
214
215         g_return_val_if_fail (CAMEL_IS_NETWORK_SERVICE (service), NULL);
216
217         interface = CAMEL_NETWORK_SERVICE_GET_INTERFACE (service);
218         g_return_val_if_fail (interface->connect_sync != NULL, NULL);
219
220         return interface->connect_sync (service, cancellable, error);
221 }