Release 1.25.0 -- Buddy Idle Time, RTF
[siplcs.git] / src / miranda / miranda-transport.c
blob9aca9ebb3ad8d1e015945e4d301f8eccff19d9a5
1 /**
2 * @file miranda-transport.c
4 * pidgin-sipe
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
23 #include <windows.h>
24 #include <stdio.h>
25 #include <glib.h>
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"
34 #include "m_netlib.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;
50 HANDLE fd;
51 struct sipe_miranda_sel_entry *inputhandler;
53 SIPPROTO *pr;
55 /* Private. For locking only */
56 HANDLE hDoneEvent;
59 static void __stdcall
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;
65 LOCK;
66 transport->input(conn);
67 UNLOCK;
68 SetEvent(transport->hDoneEvent);
71 static void
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;
79 int len;
80 int readlen;
81 gboolean firstread = TRUE;
83 LOCK;
85 if (!pr->valid)
87 UNLOCK;
88 return;
91 if (!transport->fd)
93 UNLOCK;
94 return;
97 do {
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");
114 if (transport)
115 transport->error(SIPE_TRANSPORT_CONNECTION, "Read error");
117 UNLOCK;
118 return;
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");
122 UNLOCK;
123 return;
126 conn->buffer_used += len;
127 firstread = FALSE;
129 /* Equivalence indicates that there is possibly more data to read */
130 } while (len == readlen);
132 conn->buffer[conn->buffer_used] = '\0';
133 UNLOCK;
135 transport->hDoneEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
136 CallFunctionAsync(transport_input_cb_async, transport);
137 WaitForSingleObject(transport->hDoneEvent, INFINITE);
138 CloseHandle(transport->hDoneEvent);
141 static void
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;
147 if (!pr) return;
149 LOCK;
150 if (!fd)
152 transport->error(SIPE_TRANSPORT_CONNECTION, reason);
153 } else {
154 transport->fd = fd;
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);
159 UNLOCK;
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;
176 transport->pr = pr;
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);
198 g_free(transport);
201 gchar *sipe_backend_transport_ip_address(struct sipe_transport_connection *conn)
203 // @TODO: provide correct implementation for Miranda
204 return("0.0.0.0");
207 void sipe_backend_transport_message(struct sipe_transport_connection *conn,
208 const gchar *buffer)
210 struct sipe_transport_miranda *transport = MIRANDA_TRANSPORT;
211 guint written = 0;
213 do {
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,
219 "Write error");
220 return;
223 written += len;
224 } while (written < strlen(buffer));
227 void sipe_backend_transport_flush(struct sipe_transport_connection *conn)
229 /* N/A */
233 Local Variables:
234 mode: c
235 c-file-style: "bsd"
236 indent-tabs-mode: t
237 tab-width: 8
238 End: