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-backend.h"
36 #include "newpluginapi.h"
37 #include "m_protosvc.h"
38 #include "m_protoint.h"
40 #include "miranda-private.h"
42 #define MIRANDA_TRANSPORT ((struct sipe_transport_miranda *) conn)
43 #define SIPE_TRANSPORT_CONNECTION ((struct sipe_transport_connection *) transport)
45 #define BUFFER_SIZE_INCREMENT 4096
47 struct sipe_transport_miranda
{
48 /* public part shared with core */
49 struct sipe_transport_connection
public;
51 /* miranda private part */
52 transport_connected_cb
*connected
;
53 transport_input_cb
*input
;
54 transport_error_cb
*error
;
56 struct sipe_miranda_sel_entry
*inputhandler
;
60 /* Private. For locking only */
65 transport_input_cb_async(void *data
)
67 struct sipe_transport_miranda
*transport
= (struct sipe_transport_miranda
*)data
;
68 struct sipe_transport_connection
*conn
= SIPE_TRANSPORT_CONNECTION
;
69 SIPPROTO
*pr
= transport
->pr
;
71 transport
->input(conn
);
73 SetEvent(transport
->hDoneEvent
);
77 miranda_sipe_input_cb(gpointer data
,
78 SIPE_UNUSED_PARAMETER gint source
,
79 SIPE_UNUSED_PARAMETER sipe_miranda_input_condition cond
)
81 struct sipe_transport_miranda
*transport
= (struct sipe_transport_miranda
*)data
;
82 struct sipe_transport_connection
*conn
= SIPE_TRANSPORT_CONNECTION
;
83 SIPPROTO
*pr
= transport
->pr
;
86 gboolean firstread
= TRUE
;
103 /* Increase input buffer size as needed */
104 if (conn
->buffer_length
< conn
->buffer_used
+ BUFFER_SIZE_INCREMENT
) {
105 conn
->buffer_length
+= BUFFER_SIZE_INCREMENT
;
106 conn
->buffer
= g_realloc(conn
->buffer
, conn
->buffer_length
);
107 SIPE_DEBUG_INFO("miranda_sipe_input_cb: new buffer length %" G_GSIZE_FORMAT
,
108 conn
->buffer_length
);
111 /* Try to read as much as there is space left in the buffer */
112 /* minus 1 for the string terminator */
113 readlen
= conn
->buffer_length
- conn
->buffer_used
- 1;
115 len
= Netlib_Recv(transport
->fd
, conn
->buffer
+ conn
->buffer_used
, readlen
, MSG_NODUMP
);
117 if (len
== SOCKET_ERROR
) {
118 SIPE_DEBUG_INFO("miranda_sipe_input_cb: read error");
120 transport
->error(SIPE_TRANSPORT_CONNECTION
, "Read error");
124 } else if (firstread
&& (len
== 0)) {
125 SIPE_DEBUG_ERROR_NOFORMAT("miranda_sipe_input_cb: server has disconnected");
126 transport
->error(SIPE_TRANSPORT_CONNECTION
, "Server has disconnected");
131 conn
->buffer_used
+= len
;
134 /* Equivalence indicates that there is possibly more data to read */
135 } while (len
== readlen
);
137 conn
->buffer
[conn
->buffer_used
] = '\0';
140 transport
->hDoneEvent
= CreateEvent(NULL
, FALSE
, FALSE
, NULL
);
141 CallFunctionAsync(transport_input_cb_async
, transport
);
142 WaitForSingleObject(transport
->hDoneEvent
, INFINITE
);
143 CloseHandle(transport
->hDoneEvent
);
147 connected_callback(HANDLE fd
, void* data
, const gchar
*reason
)
149 struct sipe_transport_miranda
*transport
= (struct sipe_transport_miranda
*)data
;
150 SIPPROTO
*pr
= transport
->pr
;
155 transport
->error(SIPE_TRANSPORT_CONNECTION
, reason
);
158 transport
->public.client_port
= sipe_miranda_network_get_port_from_fd( transport
->fd
);
159 transport
->inputhandler
= sipe_miranda_input_add(transport
->fd
, SIPE_MIRANDA_INPUT_READ
, miranda_sipe_input_cb
, transport
);
160 transport
->connected(SIPE_TRANSPORT_CONNECTION
);
165 struct sipe_transport_connection
*
166 sipe_backend_transport_connect(struct sipe_core_public
*sipe_public
,
167 const sipe_connect_setup
*setup
)
169 struct sipe_transport_miranda
*transport
= g_new0(struct sipe_transport_miranda
, 1);
170 SIPPROTO
*pr
= sipe_public
->backend_private
;
172 NETLIBOPENCONNECTION ncon
= {0};
174 transport
->public.type
= setup
->type
;
175 transport
->public.user_data
= setup
->user_data
;
176 transport
->connected
= setup
->connected
;
177 transport
->input
= setup
->input
;
178 transport
->error
= setup
->error
;
181 sipe_miranda_connect(pr
, setup
->server_name
, setup
->server_port
, (setup
->type
== SIPE_TRANSPORT_TLS
), 5, connected_callback
, transport
);
183 return(SIPE_TRANSPORT_CONNECTION
);
186 void sipe_backend_transport_disconnect(struct sipe_transport_connection
*conn
)
188 struct sipe_transport_miranda
*transport
= MIRANDA_TRANSPORT
;
190 SIPE_DEBUG_INFO("Disconnecting transport <%08x>", transport
);
192 if (!transport
) return;
194 Netlib_CloseHandle(transport
->fd
);
195 transport
->fd
= NULL
;
197 if (transport
->inputhandler
)
198 sipe_miranda_input_remove(transport
->inputhandler
);
200 g_free(transport
->public.buffer
);
204 void sipe_backend_transport_message(struct sipe_transport_connection
*conn
,
207 struct sipe_transport_miranda
*transport
= MIRANDA_TRANSPORT
;
211 int len
= Netlib_Send(transport
->fd
, buffer
+ written
, strlen(buffer
+ written
), MSG_NODUMP
);
213 if (len
== SOCKET_ERROR
) {
214 SIPE_DEBUG_INFO_NOFORMAT("sipe_backend_transport_message: error, exiting");
215 transport
->error(SIPE_TRANSPORT_CONNECTION
,
221 } while (written
< strlen(buffer
));
224 void sipe_backend_transport_flush(struct sipe_transport_connection
*conn
)