webticket: implement caching
[siplcs.git] / src / miranda / miranda-transport.c
blob828166ed4a3decd950713fa583d8f102deffb58e
1 /**
2 * @file miranda-transport.c
4 * pidgin-sipe
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
23 #include <windows.h>
24 #include <stdio.h>
25 #include <glib.h>
27 #ifdef HAVE_CONFIG_H
28 #include "config.h"
29 #endif
31 #include "sipe-common.h"
32 #include "sipe-core.h"
33 #include "sipe-backend.h"
34 #include "sipe-nls.h"
36 #include "newpluginapi.h"
37 #include "m_protosvc.h"
38 #include "m_protoint.h"
39 #include "m_netlib.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;
55 HANDLE fd;
56 struct sipe_miranda_sel_entry *inputhandler;
58 SIPPROTO *pr;
60 /* Private. For locking only */
61 HANDLE hDoneEvent;
64 static void __stdcall
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;
70 LOCK;
71 transport->input(conn);
72 UNLOCK;
73 SetEvent(transport->hDoneEvent);
76 static void
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;
84 int len;
85 int readlen;
86 gboolean firstread = TRUE;
88 LOCK;
90 if (!pr->valid)
92 UNLOCK;
93 return;
96 if (!transport->fd)
98 UNLOCK;
99 return;
102 do {
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");
119 if (transport)
120 transport->error(SIPE_TRANSPORT_CONNECTION, "Read error");
122 UNLOCK;
123 return;
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");
127 UNLOCK;
128 return;
131 conn->buffer_used += len;
132 firstread = FALSE;
134 /* Equivalence indicates that there is possibly more data to read */
135 } while (len == readlen);
137 conn->buffer[conn->buffer_used] = '\0';
138 UNLOCK;
140 transport->hDoneEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
141 CallFunctionAsync(transport_input_cb_async, transport);
142 WaitForSingleObject(transport->hDoneEvent, INFINITE);
143 CloseHandle(transport->hDoneEvent);
146 static void
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;
152 LOCK;
153 if (!fd)
155 transport->error(SIPE_TRANSPORT_CONNECTION, reason);
156 } else {
157 transport->fd = fd;
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);
162 UNLOCK;
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;
179 transport->pr = pr;
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);
201 g_free(transport);
204 void sipe_backend_transport_message(struct sipe_transport_connection *conn,
205 const gchar *buffer)
207 struct sipe_transport_miranda *transport = MIRANDA_TRANSPORT;
208 guint written = 0;
210 do {
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,
216 "Write error");
217 return;
220 written += len;
221 } while (written < strlen(buffer));
224 void sipe_backend_transport_flush(struct sipe_transport_connection *conn)
226 /* N/A */
230 Local Variables:
231 mode: c
232 c-file-style: "bsd"
233 indent-tabs-mode: t
234 tab-width: 8
235 End: