/*
 * mzsocket: BSD/POSIX sockets library for mzscheme
 * Copyright (C) 2007 Dimitris Vyzovitis <vyzo@media.mit.edu>
 * 
 * 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
 */
#include "_socket.h"

#define SYMBOL scheme_intern_symbol
#define FIXNUM scheme_make_integer
#define IMMUTABLE_BYTES(x) \
  scheme_make_immutable_sized_byte_string(x, strlen(x), 1)

#define EXPORT_CONST(name) \
  scheme_add_global( #name, FIXNUM(name), module )
#define EXPORT_ERRNO(name) \
  scheme_add_global( "errno:"#name, FIXNUM(name), module )
#define EXPORT_VAL(name, val) \
  scheme_add_global( #name, val, module )


Scheme_Object* scheme_reload( Scheme_Env* env ) {
  Scheme_Env* module;
  module = scheme_primitive_module( SYMBOL( "_constants" ), env );

  EXPORT_CONST( SHUT_RD );
  EXPORT_CONST( SHUT_WR );
  EXPORT_CONST( SHUT_RDWR );

  EXPORT_CONST( IPPROTO_IP );
  EXPORT_CONST( IPPROTO_TCP );
  EXPORT_CONST( IPPROTO_UDP );
  EXPORT_CONST( IPPROTO_ICMP );

  EXPORT_CONST( AF_UNSPEC );
  EXPORT_CONST( PF_UNSPEC );
  EXPORT_CONST( AF_INET );
  EXPORT_CONST( PF_INET );

  EXPORT_CONST( SOL_SOCKET );
  
  EXPORT_CONST( SOCK_STREAM );
  EXPORT_CONST( SOCK_DGRAM );

#ifdef HAVE_RAW
  EXPORT_VAL( SOCKET_HAVE_RAW, scheme_true );
  EXPORT_CONST( IPPROTO_RAW );
  EXPORT_CONST( SOCK_RAW );
#else
  EXPORT_VAL( SOCKET_HAVE_RAW, scheme_false );
#endif

#ifdef HAVE_IPV6
  EXPORT_VAL( SOCKET_HAVE_IPV6, scheme_true );
  EXPORT_CONST( IPPROTO_IPV6 );
  EXPORT_CONST( AF_INET6 );
  EXPORT_CONST( PF_INET6 );
#else 
  EXPORT_VAL( SOCKET_HAVE_IPV6, scheme_false );
  EXPORT_VAL( AF_INET6, scheme_void );
  EXPORT_VAL( PF_INET6, scheme_void );
#endif

#ifdef UNIX
  EXPORT_VAL( SOCKET_HAVE_UNIX, scheme_true );
  EXPORT_CONST( AF_UNIX );
  EXPORT_CONST( PF_UNIX );
#else
  EXPORT_VAL( SOCKET_HAVE_UNIX, scheme_false );
  EXPORT_VAL( AF_UNIX, scheme_void );
  EXPORT_VAL( PF_UNIX, scheme_void );
#endif

  // sockopts
#include "sockopt.export"

  // errno
  EXPORT_ERRNO( EACCES );
  EXPORT_ERRNO( EAFNOSUPPORT );
  EXPORT_ERRNO( EPFNOSUPPORT );
  EXPORT_ERRNO( EPROTONOSUPPORT );
  EXPORT_ERRNO( ENOBUFS );
  EXPORT_ERRNO( EFAULT );
  EXPORT_ERRNO( EADDRINUSE );
  EXPORT_ERRNO( EINVAL );
  EXPORT_ERRNO( ENOTSOCK );
  EXPORT_ERRNO( EOPNOTSUPP );
  EXPORT_ERRNO( EWOULDBLOCK );
  EXPORT_ERRNO( ECONNABORTED );
  EXPORT_ERRNO( EMFILE );
  EXPORT_ERRNO( ETIMEDOUT );
  EXPORT_ERRNO( ESOCKTNOSUPPORT );
  EXPORT_ERRNO( EALREADY );
  EXPORT_ERRNO( ECONNREFUSED );
  EXPORT_ERRNO( EISCONN );
  EXPORT_ERRNO( ENETUNREACH );
  EXPORT_ERRNO( ECONNRESET );
  EXPORT_ERRNO( EDESTADDRREQ );
  EXPORT_ERRNO( EMSGSIZE );
  EXPORT_ERRNO( ENOTCONN );
  EXPORT_ERRNO( EPROTOTYPE );
  EXPORT_ERRNO( ENOPROTOOPT ); // this really should be impossible
  EXPORT_ERRNO( EINPROGRESS ); // suppressed in connect
  EXPORT_ERRNO( EADDRNOTAVAIL );
  EXPORT_ERRNO( ENETDOWN );
  EXPORT_ERRNO( ENETRESET );
  EXPORT_ERRNO( ESHUTDOWN ); // unlikely
  EXPORT_ERRNO( EHOSTDOWN );
  EXPORT_ERRNO( EHOSTUNREACH );
  EXPORT_ERRNO( ENOMEM ); // WSA_NOT_ENOUGH_MEMORY
  EXPORT_ERRNO( ENFILE );
  EXPORT_ERRNO( EBADF );
  EXPORT_ERRNO( EPIPE );

  EXPORT_VAL( INADDR_ANY, IMMUTABLE_BYTES("0.0.0.0"));
  EXPORT_VAL( INADDR_LOOPBACK, IMMUTABLE_BYTES("127.0.0.1"));
  EXPORT_VAL( INADDR_BROADCAST, IMMUTABLE_BYTES("255.255.255.255"));
#ifdef HAVE_IPV6
  EXPORT_VAL( IN6ADDR_ANY, IMMUTABLE_BYTES("::"));
  EXPORT_VAL( IN6ADDR_LOOPBACK, IMMUTABLE_BYTES( "::1" ));
#endif
  
  scheme_finish_primitive_module( module );
  return scheme_void;
}

Scheme_Object* scheme_initialize( Scheme_Env* env ) {
  return scheme_reload( env );
}

Scheme_Object* scheme_module_name() {
  return SYMBOL( "_constants" );
}

