Fix #3161273: Lost Connection Gives No Error Message (part IV)
[siplcs.git] / src / miranda / miranda-transport.c
blobbe8a1c6f3ccf12af028d91144610742532502d5f
1 /**
2 * @file miranda-transport.c
4 * pidgin-sipe
6 * Copyright (C) 2010 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-core-private.h"
34 #include "sipe-backend.h"
35 #include "sip-transport.h"
36 #include "sipe-nls.h"
38 #include "newpluginapi.h"
39 #include "m_protosvc.h"
40 #include "m_protoint.h"
41 #include "m_netlib.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;
57 HANDLE fd;
58 struct sipe_miranda_sel_entry *inputhandler;
60 SIPPROTO *pr;
63 static unsigned __stdcall connected_callback(void* data)
65 struct sipe_transport_miranda *transport = (struct sipe_transport_miranda*)data;
66 SIPE_DEBUG_INFO_NOFORMAT("About to call connected callback");
67 transport->connected(SIPE_TRANSPORT_CONNECTION);
68 return 0;
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 int len;
79 int readlen;
80 gboolean firstread = TRUE;
82 do {
83 /* Increase input buffer size as needed */
84 if (conn->buffer_length < conn->buffer_used + BUFFER_SIZE_INCREMENT) {
85 conn->buffer_length += BUFFER_SIZE_INCREMENT;
86 conn->buffer = g_realloc(conn->buffer, conn->buffer_length);
87 SIPE_DEBUG_INFO("miranda_sipe_input_cb: new buffer length %" G_GSIZE_FORMAT,
88 conn->buffer_length);
91 /* Try to read as much as there is space left in the buffer */
92 /* minus 1 for the string terminator */
93 readlen = conn->buffer_length - conn->buffer_used - 1;
95 len = Netlib_Recv(transport->fd, conn->buffer + conn->buffer_used, readlen, MSG_NODUMP);
97 if (len == SOCKET_ERROR) {
98 SIPE_DEBUG_INFO("miranda_sipe_input_cb: read error");
99 transport->error(SIPE_TRANSPORT_CONNECTION, "Read error");
101 /* FIXME: not sure if this is the right spot */
102 sipe_miranda_input_remove(transport->inputhandler);
103 transport->inputhandler = NULL;
105 return;
106 } else if (firstread && (len == 0)) {
107 SIPE_DEBUG_ERROR_NOFORMAT("miranda_sipe_input_cb: server has disconnected");
108 transport->error(SIPE_TRANSPORT_CONNECTION, "Server has disconnected");
109 return;
112 conn->buffer_used += len;
113 firstread = FALSE;
115 /* Equivalence indicates that there is possibly more data to read */
116 } while (len == readlen);
118 conn->buffer[conn->buffer_used] = '\0';
119 transport->input(conn);
122 struct sipe_transport_connection *
123 sipe_backend_transport_connect(struct sipe_core_public *sipe_public,
124 const sipe_connect_setup *setup)
126 struct sipe_transport_miranda *transport = g_new0(struct sipe_transport_miranda, 1);
127 SIPPROTO *pr = sipe_public->backend_private;
129 NETLIBOPENCONNECTION ncon = {0};
131 ncon.cbSize = sizeof(ncon);
132 ncon.flags = NLOCF_V2;
133 ncon.szHost = setup->server_name;
134 ncon.wPort = setup->server_port;
135 ncon.timeout = 5;
137 transport->public.type = setup->type;
138 transport->public.user_data = setup->user_data;
139 transport->connected = setup->connected;
140 transport->input = setup->input;
141 transport->error = setup->error;
143 transport->fd = (HANDLE)CallService(MS_NETLIB_OPENCONNECTION, (WPARAM)pr->m_hServerNetlibUser, (LPARAM)&ncon);
144 if (transport->fd == NULL) {
145 setup->error(SIPE_TRANSPORT_CONNECTION,
146 "Could not connect");
147 sipe_backend_transport_disconnect(SIPE_TRANSPORT_CONNECTION);
148 return NULL;
151 SIPE_DEBUG_INFO("miranda_sipe_create_connection: connected %d", (int)transport->fd);
153 if (setup->type == SIPE_TRANSPORT_TLS)
155 if (!CallService(MS_NETLIB_STARTSSL, (WPARAM)transport->fd, 0))
157 setup->error(SIPE_TRANSPORT_CONNECTION,
158 "Could not negotiate SSL on connection");
159 sipe_backend_transport_disconnect(SIPE_TRANSPORT_CONNECTION);
160 return NULL;
162 SIPE_DEBUG_INFO_NOFORMAT("miranda_sipe_create_connection: SSL enabled");
166 transport->public.client_port = sipe_miranda_network_get_port_from_fd( transport->fd );
167 transport->input = setup->input;
168 transport->inputhandler = sipe_miranda_input_add(transport->fd, SIPE_MIRANDA_INPUT_READ, miranda_sipe_input_cb, transport);
170 CloseHandle((HANDLE) mir_forkthreadex( connected_callback, transport, 65536, NULL ));
171 // transport->connected(SIPE_TRANSPORT_CONNECTION);
173 return(SIPE_TRANSPORT_CONNECTION);
176 void sipe_backend_transport_disconnect(struct sipe_transport_connection *conn)
178 struct sipe_transport_miranda *transport = MIRANDA_TRANSPORT;
180 SIPE_DEBUG_INFO("Disconnecting transport <%08x>", transport);
182 if (!transport) return;
184 if (transport->inputhandler)
185 sipe_miranda_input_remove(transport->inputhandler);
187 g_free(transport->public.buffer);
189 g_free(transport);
192 void sipe_backend_transport_message(struct sipe_transport_connection *conn,
193 const gchar *buffer)
195 struct sipe_transport_miranda *transport = MIRANDA_TRANSPORT;
196 guint written = 0;
198 do {
199 int len = Netlib_Send(transport->fd, buffer + written, strlen(buffer + written), MSG_NODUMP);
201 if (len == SOCKET_ERROR) {
202 SIPE_DEBUG_INFO_NOFORMAT("sipe_backend_transport_message: error, exiting");
203 transport->error(SIPE_TRANSPORT_CONNECTION,
204 "Write error");
207 written += len;
208 } while (written < strlen(buffer));
211 void sipe_backend_transport_flush(struct sipe_transport_connection *conn)
213 /* N/A */
217 Local Variables:
218 mode: c
219 c-file-style: "bsd"
220 indent-tabs-mode: t
221 tab-width: 8
222 End: