2 * @file miranda-transport.c
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
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"
38 #include "newpluginapi.h"
39 #include "m_protosvc.h"
40 #include "m_protoint.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
;
58 struct sipe_miranda_sel_entry
*inputhandler
;
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
);
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
;
80 gboolean firstread
= TRUE
;
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
,
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
;
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");
112 conn
->buffer_used
+= len
;
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
;
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
);
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
);
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
);
192 void sipe_backend_transport_message(struct sipe_transport_connection
*conn
,
195 struct sipe_transport_miranda
*transport
= MIRANDA_TRANSPORT
;
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
,
208 } while (written
< strlen(buffer
));
211 void sipe_backend_transport_flush(struct sipe_transport_connection
*conn
)