1 /*======================================================================*
2 * Copyright (C) 2008 Light Weight Event System *
3 * All rights reserved. *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the Free Software *
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, *
18 * Boston, MA 02110-1301 USA. *
19 *======================================================================*/
20 #include "lwes_net_functions.h"
29 (struct lwes_net_connection
*conn
,
37 /* error out on a NULL connection */
43 /* set up the address structure */
44 memset((char *) &conn
->mcast_addr
, 0, sizeof(conn
->mcast_addr
));
45 conn
->mcast_addr
.sin_family
= AF_INET
;
46 conn
->mcast_addr
.sin_addr
.s_addr
= inet_addr (address
);
47 conn
->mcast_addr
.sin_port
= htons ((short)port
);
50 /* and the multicast structure (which may not be used if this is a unicast
52 conn
->mreq
.imr_multiaddr
= conn
->mcast_addr
.sin_addr
;
53 if ( iface
== NULL
|| strcmp("",iface
) == 0 )
55 conn
->mreq
.imr_interface
.s_addr
= htonl (INADDR_ANY
);
59 conn
->mreq
.imr_interface
.s_addr
= inet_addr (iface
);
62 /* construct the socket */
63 if ( (conn
->socketfd
= socket (AF_INET
, SOCK_DGRAM
, 0)) < 0 )
68 /* if the address we are emitting on is a multicast address we
69 set the sockopt which uses that interface to emit on, this doesn't
71 if (IN_MULTICAST (ntohl (conn
->mcast_addr
.sin_addr
.s_addr
)))
75 struct in_addr mcastAddr
;
77 mcastAddr
.s_addr
= inet_addr (iface
);
78 if (setsockopt(conn
->socketfd
, IPPROTO_IP
, IP_MULTICAST_IF
,
79 (char *)&mcastAddr
, sizeof(mcastAddr
)) < 0 )
86 /* Setting the value for SO_SNDBF , trying for 10*MAX_MSG_SIZE */
87 for ( i
= 10 ; i
> 0 ; i
-- )
90 if (setsockopt (conn
->socketfd
, SOL_SOCKET
, SO_SNDBUF
,
91 (void*)&arg
,sizeof(arg
)) == 0)
101 /* set the size for use below */
102 conn
->sender_ip_socket_size
= (socklen_t
)sizeof(conn
->sender_ip_addr
);
109 (struct lwes_net_connection
*conn
)
116 /* check hasJoined first, as we also "join" a unicast channel, so may
117 need to do cleanup here someday */
118 if ( conn
->hasJoined
== 1 )
120 /* if we are using a multicast address we need to drop the membership
121 so that upstream routers get the message */
122 if (IN_MULTICAST (ntohl (conn
->mcast_addr
.sin_addr
.s_addr
)))
124 /* drop the multicast channel */
129 (void*)&(conn
->mreq
),
130 sizeof(conn
->mreq
)) < 0 )
137 return close(conn
->socketfd
);
142 (struct lwes_net_connection
*conn
)
146 unsigned char ttl
= 0;
151 if (IN_MULTICAST (ntohl (conn
->mcast_addr
.sin_addr
.s_addr
)))
153 if (getsockopt (conn
->socketfd
,
171 (struct lwes_net_connection
*conn
, int new_ttl
)
178 if (IN_MULTICAST (ntohl (conn
->mcast_addr
.sin_addr
.s_addr
)))
180 if (setsockopt (conn
->socketfd
,
198 (struct lwes_net_connection
*conn
)
204 return conn
->socketfd
;
209 (struct lwes_net_connection
*conn
,
215 if (conn
== NULL
|| bytes
== NULL
)
226 (struct sockaddr
* )&(conn
->mcast_addr
),
227 sizeof(conn
->mcast_addr
));
233 lwes_net_sendto_bytes
234 (struct lwes_net_connection
*conn
,
241 struct lwes_net_connection new_conn
;
244 if (conn
== NULL
|| bytes
== NULL
)
249 if (lwes_net_open (&new_conn
, address
, iface
, port
) < 0)
254 if ((size
= lwes_net_send_bytes (&new_conn
, bytes
, len
)) < 0)
259 /* There's not much we can do about a close error, and it would mask a
260 successful send, so just ignore a bad return value */
261 (void) lwes_net_close (&new_conn
);
268 (struct lwes_net_connection
*conn
)
277 if ( conn
->hasJoined
!= 1 )
281 /* set a socket option such that the socket can be reused */
282 if ( setsockopt (conn
->socketfd
,
291 /* try for as big a buffer as possible, start at 100*MAX_MSG_SIZE
292 * and work down, if you can't get a buffer of at least one max
293 * message, error out */
294 for ( i
= 100 ; i
> 0 ; i
-- )
296 arg
= MAX_MSG_SIZE
*i
;
297 if (setsockopt(conn
->socketfd
, SOL_SOCKET
, SO_RCVBUF
,
298 (void*)&arg
,sizeof(arg
)) == 0)
308 /* if we are not in a multicast connection, then the address we are
309 using to receive on will be wrong, so we will have to set
311 if (!IN_MULTICAST (ntohl (conn
->mcast_addr
.sin_addr
.s_addr
)))
313 conn
->mcast_addr
.sin_addr
.s_addr
= htonl (INADDR_ANY
);
317 /* bind to the socket */
318 if (bind (conn
->socketfd
,
319 (struct sockaddr
* )&(conn
->mcast_addr
),
320 sizeof(conn
->mcast_addr
) ) < 0 )
325 /* add the multicast channel given */
326 if (IN_MULTICAST (ntohl (conn
->mcast_addr
.sin_addr
.s_addr
)))
328 if (setsockopt (conn
->socketfd
,
331 (void*)&(conn
->mreq
),
332 sizeof(conn
->mreq
)) < 0 )
345 (struct lwes_net_connection
*conn
,
352 if (conn
== NULL
|| bytes
== NULL
)
357 if ( (ret
= lwes_net_recv_bind (conn
)) < 0)
362 ret
= recvfrom (conn
->socketfd
,
366 (struct sockaddr
*)&(conn
->sender_ip_addr
),
367 (socklen_t
*)&(conn
->sender_ip_socket_size
));
372 lwes_net_recv_bytes_by
373 (struct lwes_net_connection
*conn
,
376 unsigned int timeout_ms
)
380 struct timeval timeout
;
383 if (conn
== NULL
|| bytes
== NULL
)
388 if ((ret
= lwes_net_recv_bind (conn
)) < 0)
393 timeout
.tv_sec
=timeout_ms
/1000;
394 timeout
.tv_usec
=(timeout_ms
%1000)*1000;
397 FD_SET(conn
->socketfd
, &read_sel
);
399 /* Just wait once, as we *should* get the packet as a chunk */
400 ret
= select (conn
->socketfd
+1, &read_sel
, NULL
, NULL
, &timeout
);
406 ret
= recvfrom (conn
->socketfd
,
410 (struct sockaddr
*)&(conn
->sender_ip_addr
),
411 (socklen_t
*)&(conn
->sender_ip_socket_size
));