/* * mzsocket: BSD/POSIX sockets library for mzscheme * Copyright (C) 2007 Dimitris Vyzovitis * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA */ // macros for sockopts #define GETSOCKOPT() \ vlen = (socklen_t)sizeof(val);\ if (getsockopt( s->fd, level, opt, &val, &vlen ) < 0)\ scheme_raise( new_exn( "socket-getsockopt", ERRNO )) #define SETSOCKOPT() \ vlen = (socklen_t)sizeof(val);\ if (setsockopt( s->fd, level, opt, &val, vlen ) < 0)\ scheme_raise( new_exn( "socket-setsockopt", ERRNO ));\ return scheme_void #define GETSOCKOPT_bool() \ {\ int val;\ GETSOCKOPT();\ return BOOLEAN( val );\ } #define SETSOCKOPT_bool() \ {\ int val;\ EXPECT_BOOLEAN( "socket-setsockopt", 3 );\ val = BOOLEAN_VAL( argv[3] );\ SETSOCKOPT();\ } #define GETSOCKOPT_int() \ {\ int val;\ GETSOCKOPT();\ return FIXNUM( val );\ } #define SETSOCKOPT_int() \ {\ int val;\ EXPECT_FIXNUM( "socket-setsockopt", 3 );\ val = FIXNUM_VAL( argv[3] );\ SETSOCKOPT();\ } #define GETSOCKOPT_timeval() \ {\ struct timeval val;\ GETSOCKOPT();\ return FLONUM( val.tv_sec + val.tv_usec * 1e6 );\ } #define SETSOCKOPT_timeval() \ {\ double sval;\ struct timeval val;\ EXPECT_FLONUM( "socket-setsockopt", 3 );\ sval = FLONUM_VAL( argv[3] );\ val.tv_sec = (int)sval;\ val.tv_usec = (int)((sval - val.tv_sec) * 1e6);\ SETSOCKOPT();\ } #define GETSOCKOPT_bytes(_len) \ {\ char val[_len];\ GETSOCKOPT();\ return BYTES_SIZE( val, 40 );\ } #define SETSOCKOPT_bytes(_len) \ {\ char val[_len];\ EXPECT_BYTES( "socket-setsockopt", 3 );\ if (BYTES_LEN( argv[3] ) < sizeof(val))\ FAIL( "socket-setsockopt: bad value length" );\ memcpy( val, BYTES_VAL( argv[3] ), sizeof(val) );\ SETSOCKOPT();\ } #define GETSOCKOPT_in_addr() \ {\ struct in_addr val;\ GETSOCKOPT();\ return inet_ntop_bytes( AF_INET, &val );\ } #define SETSOCKOPT_in_addr() \ {\ struct in_addr val;\ EXPECT_BYTES( "socket-setsockopt", 3 );\ if (!(inet_pton( AF_INET, BYTES_VAL( argv[3] ), &val ) > 0)) {\ FAIL( "socket-setsockopt: bad address" );\ }\ SETSOCKOPT();\ } #define GETSOCKOPT_in6_addr() \ {\ struct in6_addr val;\ GETSOCKOPT();\ return inet_ntop_bytes( AF_INET6, &val );\ } #define SETSOCKOPT_in6_addr() \ {\ struct in6_addr val;\ EXPECT_BYTES( "socket-setsockopt", 3 );\ if (!(inet_pton( AF_INET6, BYTES_VAL( argv[3] ), &val ) > 0)) {\ FAIL( "socket-setsockopt: bad address" );\ }\ SETSOCKOPT();\ } #define SETSOCKOPT_ip_mreq() \ {\ struct ip_mreq val;\ EXPECT_PAIR( "socket-setsockopt", 3 );\ if (BYTESP( CAR( argv[3] ))) {\ if (!(inet_pton( AF_INET, BYTES_VAL( CAR( argv[3] )), \ &val.imr_multiaddr ) > 0)) {\ FAIL( "socket-setsockopt: bad address" );\ }\ } else scheme_arg_mismatch( "socket-setsockopt", \ "ip_mreq: (bytes) or (bytes . bytes)",\ argv[3] );\ if (NULLP( CDR( argv[3] ))) {\ val.imr_interface.s_addr = htonl( INADDR_ANY );\ } else if (BYTESP( CDR( argv[3] ))) {\ if (!(inet_pton( AF_INET, BYTES_VAL( CDR( argv[3] )), \ &val.imr_interface ) > 0)) {\ FAIL( "socket-setsockopt: bad address" );\ }\ } else scheme_arg_mismatch( "socket-setsockopt", \ "ip_mreq: (bytes) or (bytes . bytes)",\ argv[3] );\ SETSOCKOPT();\ } #define SETSOCKOPT_ipv6_mreq() \ {\ struct ipv6_mreq val;\ EXPECT_PAIR( "socket-setsockopt", 3 );\ if (BYTESP( CAR( argv[3] ))) {\ if (!(inet_pton( AF_INET6, BYTES_VAL( CAR( argv[3] )), \ &val.ipv6mr_multiaddr ) > 0)) {\ FAIL( "socket-setsockopt: bad address" );\ }\ } else scheme_arg_mismatch( "socket-setsockopt", \ "ipv6_mreq: (bytes) or (bytes . int)", \ argv[3] );\ if (NULLP( CDR( argv[3] ))) {\ val.ipv6mr_interface = 0;\ } else if (FIXNUMP( CDR( argv[3] ))) {\ val.ipv6mr_interface = FIXNUM_VAL( CDR( argv[3] ));\ } else scheme_arg_mismatch( "socket-setsockopt", \ "ipv6_mreq: (bytes) or (bytes . int)", \ argv[3] );\ SETSOCKOPT();\ }