2 * @file purple-network.c
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
24 #include "config.h" /* coverity[hfa: FALSE] */
31 #include "conversation.h"
33 #include "eventloop.h"
36 /* wrappers for write() & friends for socket handling */
37 #include "win32/win32dep.h"
40 #include <sys/types.h>
41 #include <sys/socket.h>
42 #include <arpa/inet.h>
49 #include "sipe-common.h"
50 #include "sipe-backend.h"
51 #include "purple-private.h"
53 struct sipe_backend_listendata
{
54 sipe_listen_start_cb listen_cb
;
55 sipe_client_connected_cb connect_cb
;
57 PurpleNetworkListenData
*listener
;
65 client_connected_cb(struct sipe_backend_listendata
*ldata
, gint listenfd
,
66 SIPE_UNUSED_PARAMETER PurpleInputCondition cond
)
68 struct sockaddr_in saddr
;
69 socklen_t slen
= sizeof (saddr
);
71 int fd
= accept(listenfd
, (struct sockaddr
*)&saddr
, &slen
);
73 purple_input_remove(ldata
->watcher
);
79 if (ldata
->connect_cb
) {
80 ldata
->connect_cb(sipe_backend_fd_from_int(fd
), ldata
->data
);
90 backend_listen_cb(int listenfd
, struct sipe_backend_listendata
*ldata
)
92 struct sockaddr_in addr
;
93 socklen_t socklen
= sizeof (addr
);
96 ldata
->listener
= NULL
;
97 ldata
->listenfd
= listenfd
;
99 /* ignore error code */
100 (void) getsockname(listenfd
, (struct sockaddr
*)&addr
, &socklen
);
101 if (ldata
->listen_cb
)
102 ldata
->listen_cb(ntohs(addr
.sin_port
), ldata
->data
);
104 ldata
->watcher
= purple_input_add(listenfd
, PURPLE_INPUT_READ
,
105 (PurpleInputFunction
)client_connected_cb
,
109 struct sipe_backend_listendata
*
110 sipe_backend_network_listen_range(unsigned short port_min
,
111 unsigned short port_max
,
112 sipe_listen_start_cb listen_cb
,
113 sipe_client_connected_cb connect_cb
,
116 struct sipe_backend_listendata
*ldata
;
117 ldata
= g_new0(struct sipe_backend_listendata
, 1);
119 ldata
->listen_cb
= listen_cb
;
120 ldata
->connect_cb
= connect_cb
;
122 ldata
->listener
= purple_network_listen_range(port_min
, port_max
,
123 #if PURPLE_VERSION_CHECK(3,0,0)
124 /* @TODO: does FT work with IPv6? */
128 #if PURPLE_VERSION_CHECK(3,0,0)
129 /* @TODO: should we allow external mapping? */
132 (PurpleNetworkListenCallback
)backend_listen_cb
,
135 if (!ldata
->listener
) {
143 void sipe_backend_network_listen_cancel(struct sipe_backend_listendata
*ldata
)
145 g_return_if_fail(ldata
);
148 purple_network_listen_cancel(ldata
->listener
);
150 close(ldata
->listenfd
);
154 struct sipe_backend_fd
*
155 sipe_backend_fd_from_int(int fd
)
157 struct sipe_backend_fd
*sipe_fd
= g_new(struct sipe_backend_fd
, 1);
163 sipe_backend_fd_is_valid(struct sipe_backend_fd
*fd
)
165 return fd
&& fd
->fd
>= 0;
169 sipe_backend_fd_free(struct sipe_backend_fd
*fd
)