2 * @file miranda-transport.c
6 * Copyright (C) 2010-11 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
31 #include "sipe-common.h"
32 #include "sipe-core.h"
33 #include "sipe-core-private.h"
34 #include "sipe-backend.h"
35 #include "sip-transport.h"
38 #include "newpluginapi.h"
39 #include "m_protosvc.h"
40 #include "m_protoint.h"
42 #include "miranda-private.h"
44 #define MIRANDA_TRANSPORT ((struct sipe_transport_miranda *) conn)
45 #define SIPE_TRANSPORT_CONNECTION ((struct sipe_transport_connection *) transport)
47 #define BUFFER_SIZE_INCREMENT 4096
49 struct sipe_transport_miranda
{
50 /* public part shared with core */
51 struct sipe_transport_connection
public;
53 /* miranda private part */
54 transport_connected_cb
*connected
;
55 transport_input_cb
*input
;
56 transport_error_cb
*error
;
58 struct sipe_miranda_sel_entry
*inputhandler
;
64 miranda_sipe_input_cb(gpointer data
,
65 SIPE_UNUSED_PARAMETER gint source
,
66 SIPE_UNUSED_PARAMETER sipe_miranda_input_condition cond
)
68 struct sipe_transport_miranda
*transport
= (struct sipe_transport_miranda
*)data
;
69 struct sipe_transport_connection
*conn
= SIPE_TRANSPORT_CONNECTION
;
70 SIPPROTO
*pr
= transport
->pr
;
73 gboolean firstread
= TRUE
;
84 /* Increase input buffer size as needed */
85 if (conn
->buffer_length
< conn
->buffer_used
+ BUFFER_SIZE_INCREMENT
) {
86 conn
->buffer_length
+= BUFFER_SIZE_INCREMENT
;
87 conn
->buffer
= g_realloc(conn
->buffer
, conn
->buffer_length
);
88 SIPE_DEBUG_INFO("miranda_sipe_input_cb: new buffer length %" G_GSIZE_FORMAT
,
92 /* Try to read as much as there is space left in the buffer */
93 /* minus 1 for the string terminator */
94 readlen
= conn
->buffer_length
- conn
->buffer_used
- 1;
96 len
= Netlib_Recv(transport
->fd
, conn
->buffer
+ conn
->buffer_used
, readlen
, MSG_NODUMP
);
98 if (len
== SOCKET_ERROR
) {
99 SIPE_DEBUG_INFO("miranda_sipe_input_cb: read error");
102 transport
->error(SIPE_TRANSPORT_CONNECTION
, "Read error");
104 // /* FIXME: not sure if this is the right spot */
105 sipe_miranda_input_remove(transport
->inputhandler
);
106 transport
->inputhandler
= NULL
;
111 } else if (firstread
&& (len
== 0)) {
112 SIPE_DEBUG_ERROR_NOFORMAT("miranda_sipe_input_cb: server has disconnected");
113 transport
->error(SIPE_TRANSPORT_CONNECTION
, "Server has disconnected");
118 conn
->buffer_used
+= len
;
121 /* Equivalence indicates that there is possibly more data to read */
122 } while (len
== readlen
);
124 conn
->buffer
[conn
->buffer_used
] = '\0';
125 transport
->input(conn
);
130 connected_callback(HANDLE fd
, void* data
, const gchar
*reason
)
132 struct sipe_transport_miranda
*transport
= (struct sipe_transport_miranda
*)data
;
133 SIPPROTO
*pr
= transport
->pr
;
138 transport
->error(SIPE_TRANSPORT_CONNECTION
, reason
);
141 transport
->public.client_port
= sipe_miranda_network_get_port_from_fd( transport
->fd
);
142 transport
->inputhandler
= sipe_miranda_input_add(transport
->fd
, SIPE_MIRANDA_INPUT_READ
, miranda_sipe_input_cb
, transport
);
143 transport
->connected(SIPE_TRANSPORT_CONNECTION
);
148 struct sipe_transport_connection
*
149 sipe_backend_transport_connect(struct sipe_core_public
*sipe_public
,
150 const sipe_connect_setup
*setup
)
152 struct sipe_transport_miranda
*transport
= g_new0(struct sipe_transport_miranda
, 1);
153 SIPPROTO
*pr
= sipe_public
->backend_private
;
155 NETLIBOPENCONNECTION ncon
= {0};
157 transport
->public.type
= setup
->type
;
158 transport
->public.user_data
= setup
->user_data
;
159 transport
->connected
= setup
->connected
;
160 transport
->input
= setup
->input
;
161 transport
->error
= setup
->error
;
164 sipe_miranda_connect(pr
, setup
->server_name
, setup
->server_port
, (setup
->type
== SIPE_TRANSPORT_TLS
), 5, connected_callback
, transport
);
166 return(SIPE_TRANSPORT_CONNECTION
);
169 void sipe_backend_transport_disconnect(struct sipe_transport_connection
*conn
)
171 struct sipe_transport_miranda
*transport
= MIRANDA_TRANSPORT
;
173 SIPE_DEBUG_INFO("Disconnecting transport <%08x>", transport
);
175 if (!transport
) return;
177 Netlib_CloseHandle(transport
->fd
);
178 transport
->fd
= NULL
;
180 if (transport
->inputhandler
)
181 sipe_miranda_input_remove(transport
->inputhandler
);
183 g_free(transport
->public.buffer
);
187 void sipe_backend_transport_message(struct sipe_transport_connection
*conn
,
190 struct sipe_transport_miranda
*transport
= MIRANDA_TRANSPORT
;
194 int len
= Netlib_Send(transport
->fd
, buffer
+ written
, strlen(buffer
+ written
), MSG_NODUMP
);
196 if (len
== SOCKET_ERROR
) {
197 SIPE_DEBUG_INFO_NOFORMAT("sipe_backend_transport_message: error, exiting");
198 transport
->error(SIPE_TRANSPORT_CONNECTION
,
204 } while (written
< strlen(buffer
));
207 void sipe_backend_transport_flush(struct sipe_transport_connection
*conn
)