2 * @file telepathy-transport.c
6 * Copyright (C) 2012 SIPE Project <http://sipe.sourceforge.net/>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
32 #include "sipe-backend.h"
33 #include "sipe-common.h"
34 #include "sipe-core.h"
37 #include "telepathy-private.h"
39 struct sipe_transport_telepathy
{
40 /* public part shared with core */
41 struct sipe_transport_connection
public;
43 /* telepathy private part */
44 transport_connected_cb
*connected
;
45 transport_input_cb
*input
;
46 transport_error_cb
*error
;
47 struct sipe_backend_private
*private;
48 GSocketConnection
*socket
;
49 GInputStream
*istream
;
50 GOutputStream
*ostream
;
53 #define TELEPATHY_TRANSPORT ((struct sipe_transport_telepathy *) conn)
54 #define SIPE_TRANSPORT_CONNECTION ((struct sipe_transport_connection *) transport)
56 #define BUFFER_SIZE_INCREMENT 4096
58 static void read_completed(GObject
*stream
,
62 struct sipe_transport_telepathy
*transport
= data
;
63 struct sipe_transport_connection
*conn
= SIPE_TRANSPORT_CONNECTION
;
65 if (conn
->buffer_length
< conn
->buffer_used
+ BUFFER_SIZE_INCREMENT
) {
66 conn
->buffer_length
+= BUFFER_SIZE_INCREMENT
;
67 conn
->buffer
= g_realloc(conn
->buffer
, conn
->buffer_length
);
68 SIPE_DEBUG_INFO("read_completed: new buffer length %" G_GSIZE_FORMAT
,
72 /* callback result is valid */
75 gssize len
= g_input_stream_read_finish(G_INPUT_STREAM(stream
),
80 SIPE_DEBUG_ERROR("read error: %s", error
->message
);
81 transport
->error(conn
, error
->message
);
84 } else if (len
== 0) {
85 SIPE_DEBUG_ERROR_NOFORMAT("Server has disconnected");
86 transport
->error(conn
, _("Server has disconnected"));
90 /* Forward data to core */
91 conn
->buffer_used
+= len
;
92 conn
->buffer
[conn
->buffer_used
] = '\0';
93 transport
->input(conn
);
97 g_input_stream_read_async(G_INPUT_STREAM(stream
),
98 conn
->buffer
+ conn
->buffer_used
,
99 conn
->buffer_length
- conn
->buffer_used
- 1,
106 static void socket_connected(GObject
*client
,
107 GAsyncResult
*result
,
110 struct sipe_transport_telepathy
*transport
= data
;
111 GError
*error
= NULL
;
113 transport
->socket
= g_socket_client_connect_finish(G_SOCKET_CLIENT(client
),
117 if (transport
->socket
) {
118 SIPE_DEBUG_INFO_NOFORMAT("socket_connected: success");
119 transport
->istream
= g_io_stream_get_input_stream(G_IO_STREAM(transport
->socket
));
120 transport
->ostream
= g_io_stream_get_output_stream(G_IO_STREAM(transport
->socket
));
121 /* this sets up the async read handler */
122 read_completed(G_OBJECT(transport
->istream
), NULL
, transport
);
123 transport
->connected(SIPE_TRANSPORT_CONNECTION
);
125 SIPE_DEBUG_ERROR("socket_connected: failed: %s", error
->message
);
126 transport
->error(SIPE_TRANSPORT_CONNECTION
, error
->message
);
130 struct sipe_transport_connection
*sipe_backend_transport_connect(struct sipe_core_public
*sipe_public
,
131 const sipe_connect_setup
*setup
)
133 struct sipe_transport_telepathy
*transport
= g_new0(struct sipe_transport_telepathy
, 1);
134 struct sipe_backend_private
*telepathy_private
= sipe_public
->backend_private
;
136 SIPE_DEBUG_INFO("sipe_backend_transport_connect - hostname: %s port: %d",
137 setup
->server_name
, setup
->server_port
);
139 transport
->public.type
= setup
->type
;
140 transport
->public.user_data
= setup
->user_data
;
141 transport
->connected
= setup
->connected
;
142 transport
->input
= setup
->input
;
143 transport
->error
= setup
->error
;
144 transport
->private = telepathy_private
;
146 if ((setup
->type
== SIPE_TRANSPORT_TLS
) ||
147 (setup
->type
== SIPE_TRANSPORT_TCP
)) {
148 GSocketClient
*client
= g_socket_client_new();
150 /* request TLS connection */
151 if (setup
->type
== SIPE_TRANSPORT_TLS
) {
152 SIPE_DEBUG_INFO_NOFORMAT("using TLS");
153 g_socket_client_set_tls(client
,
154 setup
->type
== SIPE_TRANSPORT_TLS
);
155 /* @TODO certificate handling - now accept all*/
156 g_socket_client_set_tls_validation_flags(client
, 0);
158 SIPE_DEBUG_INFO_NOFORMAT("using TCP");
160 g_socket_client_connect_async(client
,
161 g_network_address_new(setup
->server_name
,
166 g_object_unref(client
);
168 setup
->error(SIPE_TRANSPORT_CONNECTION
,
169 "This should not happen...");
170 sipe_backend_transport_disconnect(SIPE_TRANSPORT_CONNECTION
);
174 /* the first connection is always to the server */
175 if (telepathy_private
->transport
== NULL
)
176 telepathy_private
->transport
= transport
;
178 return(SIPE_TRANSPORT_CONNECTION
);
181 void sipe_backend_transport_disconnect(struct sipe_transport_connection
*conn
)
183 struct sipe_transport_telepathy
*transport
= TELEPATHY_TRANSPORT
;
185 if (!transport
) return;
187 if (transport
->socket
)
188 g_object_unref(transport
->socket
);
190 /* connection to the server dropped? */
191 if (transport
->private->transport
== transport
)
192 transport
->private->transport
= NULL
;
197 static void write_completed(GObject
*stream
,
198 GAsyncResult
*result
,
201 struct sipe_transport_telepathy
*transport
= data
;
202 GError
*error
= NULL
;
204 g_output_stream_write_finish(G_OUTPUT_STREAM(stream
), result
, &error
);
207 SIPE_DEBUG_ERROR("write error: %s", error
->message
);
208 transport
->error(SIPE_TRANSPORT_CONNECTION
, error
->message
);
213 void sipe_backend_transport_message(struct sipe_transport_connection
*conn
,
216 struct sipe_transport_telepathy
*transport
= TELEPATHY_TRANSPORT
;
217 g_output_stream_write_async(transport
->ostream
,
226 void sipe_backend_transport_flush(struct sipe_transport_connection
*conn
)
228 struct sipe_transport_telepathy
*transport
= TELEPATHY_TRANSPORT
;
229 g_output_stream_flush(transport
->ostream
, NULL
, NULL
);