2 * @file miranda-network.c
6 * Copyright (C) 2010-12 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
28 #include "newpluginapi.h"
29 #include "m_protosvc.h"
30 #include "m_protoint.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 const gchar
*sipe_backend_network_ip_address(SIPE_UNUSED_PARAMETER
struct sipe_core_public
*sipe_public
)
49 static gchar ip
[60] = "\0";
52 sipe_miranda_getGlobalWord("iptype", &iptype
);
54 if (iptype
== SIPE_MIRANDA_IP_LOCAL
)
56 struct hostent
*localHost
= gethostbyname("");
57 gchar
*localIP
= inet_ntoa(*(struct in_addr
*)*localHost
->h_addr_list
);
58 strncpy(ip
, localIP
, 60);
59 SIPE_DEBUG_INFO("Local ip is <%s>", ip
);
60 } else if (iptype
== SIPE_MIRANDA_IP_MANUAL
) {
61 gchar
*tmp
= sipe_miranda_getGlobalString("public_ip");
62 SIPE_DEBUG_INFO("Retrieving public ip option: <%s>", tmp
);
66 DWORD bytesread
= sizeof(ip
);
67 gchar
*cmd
= sipe_miranda_getGlobalString("ipprog");
68 gchar
*cmdline
= g_strdup_printf("%s ip", cmd
);
71 SIPE_DEBUG_INFO("Running command to retrieve ip: <%s>", cmdline
);
72 if (!sipe_miranda_cmd(cmdline
, ip
, &bytesread
))
74 SIPE_DEBUG_INFO("Could not run child program <%s> (%d)", cmdline
, GetLastError());
87 struct sipe_backend_listendata
{
88 sipe_listen_start_cb listen_cb
;
89 sipe_client_connected_cb connect_cb
;
91 unsigned short port_min
;
92 unsigned short port_max
;
98 /* Private. For locking only */
104 static void __stdcall
105 client_connected_cb_async(void *data
)
107 struct sipe_backend_listendata
*ldata
= (struct sipe_backend_listendata
*)data
;
109 SIPE_DEBUG_INFO("[CN:%08x] About to call real connect callback", ldata
);
111 if (ldata
->connect_cb
)
112 ldata
->connect_cb((struct sipe_backend_fd
*)ldata
->fd
, ldata
->data
);
114 /* Can't close the handle before the SetEvent or we'll deadlock */
115 SetEvent(ldata
->hDoneEvent
);
116 /* MS_NETLIB_CLOSEHANDLE doesn't come back until the accept thread
117 is done. That in turn doesn't end until the pfnNewConnectionV2
118 function comes back. So we know that client_connected_callback
119 will be done and it's safe to free ldata here. */
120 CallService(MS_NETLIB_CLOSEHANDLE
,(WPARAM
)ldata
->boundport
,0);
124 static void client_connected_callback(HANDLE hNewConnection
, DWORD dwRemoteIP
, void *data
)
126 struct sipe_backend_listendata
*ldata
= (struct sipe_backend_listendata
*)data
;
128 SIPE_DEBUG_INFO("[CN:%08x] Remote connection from <%08x>", ldata
, dwRemoteIP
);
130 ldata
->fd
= hNewConnection
;
131 ldata
->hDoneEvent
= CreateEvent(NULL
, FALSE
, FALSE
, NULL
);
132 CallFunctionAsync(client_connected_cb_async
, ldata
);
133 WaitForSingleObject(ldata
->hDoneEvent
, INFINITE
);
134 CloseHandle(ldata
->hDoneEvent
);
138 static void __stdcall
139 listen_cb_async(void *data
)
141 struct sipe_backend_listendata
*ldata
= (struct sipe_backend_listendata
*)data
;
142 ldata
->listen_cb(ldata
->port
, ldata
->data
);
143 SetEvent(ldata
->hDoneEventL
);
146 static unsigned __stdcall
listen_callback(void* data
)
148 NETLIBBIND nlb
= {0};
149 NETLIBUSERSETTINGS nls
= {0};
151 struct sipe_backend_listendata
*ldata
= (struct sipe_backend_listendata
*)data
;
153 nls
.cbSize
= sizeof(NETLIBUSERSETTINGS
);
154 CallService(MS_NETLIB_GETUSERSETTINGS
, (WPARAM
)sipe_miranda_incoming_netlibuser
, (LPARAM
)&nls
);
155 nls
.specifyIncomingPorts
= 1;
156 nls
.szIncomingPorts
= mir_alloc(20);
157 mir_snprintf( nls
.szIncomingPorts
, 20, "%d-%d", ldata
->port_min
, ldata
->port_max
);
158 CallService(MS_NETLIB_SETUSERSETTINGS
, (WPARAM
)sipe_miranda_incoming_netlibuser
, (LPARAM
)&nls
);
160 nlb
.cbSize
= sizeof(NETLIBBIND
);
161 nlb
.pfnNewConnectionV2
= client_connected_callback
;
163 SetLastError(ERROR_INVALID_PARAMETER
); // this must be here - NetLib does not set any error :((
165 ldata
->boundport
= (HANDLE
)CallService(MS_NETLIB_BINDPORT
, (WPARAM
)sipe_miranda_incoming_netlibuser
, (LPARAM
)&nlb
);
166 ldata
->port
= nlb
.wPort
;
168 sipe_miranda_getGlobalWord("iptype", &iptype
);
169 if (iptype
== SIPE_MIRANDA_IP_PROG
)
172 DWORD bytesread
= sizeof(rc
);
173 gchar
*cmd
= sipe_miranda_getGlobalString("ipprog");
174 gchar
*cmdline
= g_strdup_printf("%s listen %d", cmd
, nlb
.wPort
);
177 if (!sipe_miranda_cmd(cmdline
, rc
, &bytesread
))
179 SIPE_DEBUG_INFO("Could not run child program <%s> (%d)", cmdline
, GetLastError());
183 if (ldata
->listen_cb
)
185 ldata
->hDoneEventL
= CreateEvent(NULL
, FALSE
, FALSE
, NULL
);
186 CallFunctionAsync(listen_cb_async
, ldata
);
187 WaitForSingleObject(ldata
->hDoneEventL
, INFINITE
);
188 CloseHandle(ldata
->hDoneEventL
);
194 struct sipe_backend_listendata
*
195 sipe_backend_network_listen_range(unsigned short port_min
,
196 unsigned short port_max
,
197 sipe_listen_start_cb listen_cb
,
198 sipe_client_connected_cb connect_cb
,
201 struct sipe_backend_listendata
*ldata
;
202 ldata
= g_new0(struct sipe_backend_listendata
, 1);
204 ldata
->listen_cb
= listen_cb
;
205 ldata
->connect_cb
= connect_cb
;
207 ldata
->port_min
= port_min
;
208 ldata
->port_max
= port_max
;
210 CloseHandle((HANDLE
) mir_forkthreadex( listen_callback
, ldata
, 65536, NULL
));
215 void sipe_backend_network_listen_cancel(struct sipe_backend_listendata
*ldata
)
221 sipe_backend_fd_is_valid(struct sipe_backend_fd
*fd
)
226 void sipe_backend_fd_free(struct sipe_backend_fd
*fd
)
228 /* N/A; sipe_backend_fd is the actual HANDLE */