2 * @file miranda-transport.c
6 * Copyright (C) 2010-2018 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
27 #include "sipe-common.h"
28 #include "sipe-core.h"
29 #include "sipe-backend.h"
31 #include "newpluginapi.h"
32 #include "m_protosvc.h"
33 #include "m_protoint.h"
35 #include "miranda-private.h"
37 #define MIRANDA_TRANSPORT ((struct sipe_transport_miranda *) conn)
38 #define SIPE_TRANSPORT_CONNECTION ((struct sipe_transport_connection *) transport)
40 #define BUFFER_SIZE_INCREMENT 4096
42 struct sipe_transport_miranda
{
43 /* public part shared with core */
44 struct sipe_transport_connection
public;
46 /* miranda private part */
47 transport_connected_cb
*connected
;
48 transport_input_cb
*input
;
49 transport_error_cb
*error
;
51 struct sipe_miranda_sel_entry
*inputhandler
;
55 /* Private. For locking only */
60 transport_input_cb_async(void *data
)
62 struct sipe_transport_miranda
*transport
= (struct sipe_transport_miranda
*)data
;
63 struct sipe_transport_connection
*conn
= SIPE_TRANSPORT_CONNECTION
;
64 SIPPROTO
*pr
= transport
->pr
;
66 transport
->input(conn
);
68 SetEvent(transport
->hDoneEvent
);
72 miranda_sipe_input_cb(gpointer data
,
73 SIPE_UNUSED_PARAMETER gint source
,
74 SIPE_UNUSED_PARAMETER sipe_miranda_input_condition cond
)
76 struct sipe_transport_miranda
*transport
= (struct sipe_transport_miranda
*)data
;
77 struct sipe_transport_connection
*conn
= SIPE_TRANSPORT_CONNECTION
;
78 SIPPROTO
*pr
= transport
->pr
;
81 gboolean firstread
= TRUE
;
98 /* Increase input buffer size as needed */
99 if (conn
->buffer_length
< conn
->buffer_used
+ BUFFER_SIZE_INCREMENT
) {
100 conn
->buffer_length
+= BUFFER_SIZE_INCREMENT
;
101 conn
->buffer
= g_realloc(conn
->buffer
, conn
->buffer_length
);
102 SIPE_DEBUG_INFO("miranda_sipe_input_cb: new buffer length %" G_GSIZE_FORMAT
,
103 conn
->buffer_length
);
106 /* Try to read as much as there is space left in the buffer */
107 /* minus 1 for the string terminator */
108 readlen
= conn
->buffer_length
- conn
->buffer_used
- 1;
110 len
= Netlib_Recv(transport
->fd
, conn
->buffer
+ conn
->buffer_used
, readlen
, MSG_NODUMP
);
112 if (len
== SOCKET_ERROR
) {
113 SIPE_DEBUG_INFO("miranda_sipe_input_cb: read error");
115 transport
->error(SIPE_TRANSPORT_CONNECTION
, "Read error");
119 } else if (firstread
&& (len
== 0)) {
120 SIPE_DEBUG_ERROR_NOFORMAT("miranda_sipe_input_cb: server has disconnected");
121 transport
->error(SIPE_TRANSPORT_CONNECTION
, "Server has disconnected");
126 conn
->buffer_used
+= len
;
129 /* Equivalence indicates that there is possibly more data to read */
130 } while (len
== readlen
);
132 conn
->buffer
[conn
->buffer_used
] = '\0';
135 transport
->hDoneEvent
= CreateEvent(NULL
, FALSE
, FALSE
, NULL
);
136 CallFunctionAsync(transport_input_cb_async
, transport
);
137 WaitForSingleObject(transport
->hDoneEvent
, INFINITE
);
138 CloseHandle(transport
->hDoneEvent
);
142 connected_callback(HANDLE fd
, void* data
, const gchar
*reason
)
144 struct sipe_transport_miranda
*transport
= (struct sipe_transport_miranda
*)data
;
145 SIPPROTO
*pr
= transport
->pr
;
152 transport
->error(SIPE_TRANSPORT_CONNECTION
, reason
);
155 transport
->public.client_port
= sipe_miranda_network_get_port_from_fd( transport
->fd
);
156 transport
->inputhandler
= sipe_miranda_input_add(transport
->fd
, SIPE_MIRANDA_INPUT_READ
, miranda_sipe_input_cb
, transport
);
157 transport
->connected(SIPE_TRANSPORT_CONNECTION
);
162 struct sipe_transport_connection
*
163 sipe_backend_transport_connect(struct sipe_core_public
*sipe_public
,
164 const sipe_connect_setup
*setup
)
166 struct sipe_transport_miranda
*transport
= g_new0(struct sipe_transport_miranda
, 1);
167 SIPPROTO
*pr
= sipe_public
->backend_private
;
169 NETLIBOPENCONNECTION ncon
= {0};
171 transport
->public.type
= setup
->type
;
172 transport
->public.user_data
= setup
->user_data
;
173 transport
->connected
= setup
->connected
;
174 transport
->input
= setup
->input
;
175 transport
->error
= setup
->error
;
178 sipe_miranda_connect(pr
, setup
->server_name
, setup
->server_port
, (setup
->type
== SIPE_TRANSPORT_TLS
), 5, connected_callback
, transport
);
180 return(SIPE_TRANSPORT_CONNECTION
);
183 void sipe_backend_transport_disconnect(struct sipe_transport_connection
*conn
)
185 struct sipe_transport_miranda
*transport
= MIRANDA_TRANSPORT
;
187 SIPE_DEBUG_INFO("Disconnecting transport <%08x>", transport
);
189 if (!transport
) return;
191 Netlib_CloseHandle(transport
->fd
);
192 transport
->fd
= NULL
;
194 if (transport
->inputhandler
)
195 sipe_miranda_input_remove(transport
->inputhandler
);
197 g_free(transport
->public.buffer
);
201 gchar
*sipe_backend_transport_ip_address(struct sipe_transport_connection
*conn
)
203 // @TODO: provide correct implementation for Miranda
207 void sipe_backend_transport_message(struct sipe_transport_connection
*conn
,
210 struct sipe_transport_miranda
*transport
= MIRANDA_TRANSPORT
;
214 int len
= Netlib_Send(transport
->fd
, buffer
+ written
, strlen(buffer
+ written
), MSG_NODUMP
);
216 if (len
== SOCKET_ERROR
) {
217 SIPE_DEBUG_INFO_NOFORMAT("sipe_backend_transport_message: error, exiting");
218 transport
->error(SIPE_TRANSPORT_CONNECTION
,
224 } while (written
< strlen(buffer
));
227 void sipe_backend_transport_flush(struct sipe_transport_connection
*conn
)