Release 1.25.0 -- Buddy Idle Time, RTF
[siplcs.git] / src / miranda / miranda-network.c
blobd65f060e0c418c2d11731dd6403cb8deda1ac35b
1 /**
2 * @file miranda-network.c
4 * pidgin-sipe
6 * Copyright (C) 2010-2016 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>
26 #include <glib.h>
28 #include "newpluginapi.h"
29 #include "m_protosvc.h"
30 #include "m_protoint.h"
31 #include "m_system.h"
32 #include "m_netlib.h"
34 #include "sipe-common.h"
35 #include "sipe-core.h"
36 #include "sipe-backend.h"
37 #include "miranda-private.h"
39 extern HANDLE sipe_miranda_incoming_netlibuser;
41 const gchar *sipe_miranda_get_local_ip(void)
43 struct hostent *localHost = gethostbyname("");
44 return inet_ntoa(*(struct in_addr *)*localHost->h_addr_list);
47 struct sipe_backend_listendata {
48 sipe_listen_start_cb listen_cb;
49 sipe_client_connected_cb connect_cb;
50 gpointer data;
51 unsigned short port_min;
52 unsigned short port_max;
54 HANDLE boundport;
55 HANDLE fd;
56 WORD port;
58 /* Private. For locking only */
59 HANDLE hDoneEvent;
60 HANDLE hDoneEventL;
64 static void __stdcall
65 client_connected_cb_async(void *data)
67 struct sipe_backend_listendata *ldata = (struct sipe_backend_listendata *)data;
69 SIPE_DEBUG_INFO("[CN:%08x] About to call real connect callback", ldata);
71 if (ldata->connect_cb)
72 ldata->connect_cb((struct sipe_backend_fd *)ldata->fd, ldata->data);
74 /* Can't close the handle before the SetEvent or we'll deadlock */
75 SetEvent(ldata->hDoneEvent);
76 /* MS_NETLIB_CLOSEHANDLE doesn't come back until the accept thread
77 is done. That in turn doesn't end until the pfnNewConnectionV2
78 function comes back. So we know that client_connected_callback
79 will be done and it's safe to free ldata here. */
80 CallService(MS_NETLIB_CLOSEHANDLE,(WPARAM)ldata->boundport,0);
81 g_free(ldata);
84 static void client_connected_callback(HANDLE hNewConnection, DWORD dwRemoteIP, void *data)
86 struct sipe_backend_listendata *ldata = (struct sipe_backend_listendata *)data;
88 SIPE_DEBUG_INFO("[CN:%08x] Remote connection from <%08x>", ldata, dwRemoteIP);
90 ldata->fd = hNewConnection;
91 ldata->hDoneEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
92 CallFunctionAsync(client_connected_cb_async, ldata);
93 WaitForSingleObject(ldata->hDoneEvent, INFINITE);
94 CloseHandle(ldata->hDoneEvent);
98 static void __stdcall
99 listen_cb_async(void *data)
101 struct sipe_backend_listendata *ldata = (struct sipe_backend_listendata *)data;
102 ldata->listen_cb(ldata->port, ldata->data);
103 SetEvent(ldata->hDoneEventL);
106 static unsigned __stdcall listen_callback(void* data)
108 NETLIBBIND nlb = {0};
109 NETLIBUSERSETTINGS nls = {0};
110 WORD iptype;
111 struct sipe_backend_listendata *ldata = (struct sipe_backend_listendata *)data;
113 nls.cbSize = sizeof(NETLIBUSERSETTINGS);
114 CallService(MS_NETLIB_GETUSERSETTINGS, (WPARAM)sipe_miranda_incoming_netlibuser, (LPARAM)&nls);
115 nls.specifyIncomingPorts = 1;
116 nls.szIncomingPorts = mir_alloc(20);
117 mir_snprintf( nls.szIncomingPorts, 20, "%d-%d", ldata->port_min, ldata->port_max);
118 CallService(MS_NETLIB_SETUSERSETTINGS, (WPARAM)sipe_miranda_incoming_netlibuser, (LPARAM)&nls);
120 nlb.cbSize = sizeof(NETLIBBIND);
121 nlb.pfnNewConnectionV2 = client_connected_callback;
122 nlb.pExtra = ldata;
123 SetLastError(ERROR_INVALID_PARAMETER); // this must be here - NetLib does not set any error :((
125 ldata->boundport = (HANDLE)CallService(MS_NETLIB_BINDPORT, (WPARAM)sipe_miranda_incoming_netlibuser, (LPARAM)&nlb);
126 ldata->port = nlb.wPort;
128 sipe_miranda_getGlobalWord("iptype", &iptype);
129 if (iptype == SIPE_MIRANDA_IP_PROG)
131 gchar rc[20];
132 DWORD bytesread = sizeof(rc);
133 gchar *cmd = sipe_miranda_getGlobalString("ipprog");
134 gchar *cmdline = g_strdup_printf("%s listen %d", cmd, nlb.wPort);
135 mir_free(cmd);
137 if (!sipe_miranda_cmd(cmdline, rc, &bytesread))
139 SIPE_DEBUG_INFO("Could not run child program <%s> (%d)", cmdline, GetLastError());
143 if (ldata->listen_cb)
145 ldata->hDoneEventL = CreateEvent(NULL, FALSE, FALSE, NULL);
146 CallFunctionAsync(listen_cb_async, ldata);
147 WaitForSingleObject(ldata->hDoneEventL, INFINITE);
148 CloseHandle(ldata->hDoneEventL);
151 return 0;
154 struct sipe_backend_listendata *
155 sipe_backend_network_listen_range(unsigned short port_min,
156 unsigned short port_max,
157 sipe_listen_start_cb listen_cb,
158 sipe_client_connected_cb connect_cb,
159 gpointer data)
161 struct sipe_backend_listendata *ldata;
162 ldata = g_new0(struct sipe_backend_listendata, 1);
164 ldata->listen_cb = listen_cb;
165 ldata->connect_cb = connect_cb;
166 ldata->data = data;
167 ldata->port_min = port_min;
168 ldata->port_max = port_max;
170 CloseHandle((HANDLE) mir_forkthreadex( listen_callback, ldata, 65536, NULL ));
172 return ldata;
175 void sipe_backend_network_listen_cancel(struct sipe_backend_listendata *ldata)
177 _NIF();
180 struct sipe_backend_fd *
181 sipe_backend_fd_from_int(int fd)
183 _NIF();
184 return NULL;
187 gboolean
188 sipe_backend_fd_is_valid(struct sipe_backend_fd *fd)
190 return (fd != NULL);
193 void sipe_backend_fd_free(struct sipe_backend_fd *fd)
195 /* N/A; sipe_backend_fd is the actual HANDLE */
199 Local Variables:
200 mode: c
201 c-file-style: "bsd"
202 indent-tabs-mode: t
203 tab-width: 8
204 End: