Commits

Anonymous committed e624b29

Submit cf-0.1 release.

  • Participants
  • Parent commits 0a16348

Comments (0)

Files changed (1)

File cf/cf_socket_p.c

 /*---------------------------------------------------------------------------*
   C MODULE  cf_socket_p.c
 
-  Copyright (c) 2003, James H. Woodyatt
+  Copyright (c) 2003-2004, James H. Woodyatt
   All rights reserved.
 
   Redistribution and use in source and binary forms, with or without
   are met:
 
     Redistributions of source code must retain the above copyright
-    notice, this list of conditions and the following disclaimer.
+â    notice, this list of conditions and the following disclaimer.
 
     Redistributions in binary form must reproduce the above copyright
     notice, this list of conditions and the following disclaimer in
 #include <unistd.h>
 #include <string.h>
 #include <errno.h>
+#include <stdio.h>
+
+#define FAILWITH(S)            (failwith("Cf_socket." S))
+#define INVALID_ARGUMENT(S)    (invalid_argument("Cf_socket." S))
 
 static int cf_socket_domain_compare(value v1, value v2)
 {
     CAMLparam2(v1, v2);
     int pf1, pf2;
-    
+        
     pf1 = Cf_socket_domain_val(v1)->d_domain;
     pf2 = Cf_socket_domain_val(v2)->d_domain;
     if (pf1 == pf2) {
 
 static long cf_socket_domain_hash(value v)
 {
-    CAMLparam1(v);    
+    CAMLparam1(v);
     CAMLreturn((long) Cf_socket_domain_val(v)->d_domain);
 }
 
 external domain_of_unit_sockaddr:
     unit sockaddr_t -> unit domain_t = "cf_socket_domain_of_unit_sockaddr"
   ---*/
-CAMLprim value cf_socket_domain_of_unit_sockaddr(value saVal)
+CAMLprim value cf_socket_domain_of_unit_sockaddr(value sxVal)
 {
-    CAMLparam1(saVal);
+    CAMLparam1(sxVal);
     
-    struct sockaddr* saPtr;
+    const Cf_socket_sockaddrx_unit_t* sxPtr;
     
-    saPtr = (struct sockaddr*) Data_custom_val(saVal);
-    CAMLreturn(copy_nativeint(saPtr->sa_family));
+    sxPtr = Cf_socket_sockaddrx_unit_val(sxVal);
+    CAMLreturn(copy_nativeint(sxPtr->sx_sockaddr.sa_family));
 }
 
 /*---
 CAMLprim value cf_socket_getsockname(value sockVal)
 {
     CAMLparam1(sockVal);
-    CAMLlocal1(saVal);
+    CAMLlocal1(sxVal);
 
     const Cf_socket_t* sockPtr;
-    char buffer[SOCK_MAXADDRLEN];
+    struct sockaddr_storage ss;
+    struct sockaddr* saPtr;
     int addrLen, v;
     
     sockPtr = Cf_socket_val(sockVal);
-    addrLen = sockPtr->s_domain.d_socklen;
-    v = getsockname(sockPtr->s_fd, (struct sockaddr*) buffer, &addrLen);
+    saPtr = (struct sockaddr*) &ss;
+    addrLen = sizeof ss;
+    v = getsockname(sockPtr->s_fd, saPtr, &addrLen);
     if (v == -1) uerror("getsockname", Nothing);
         
-    saVal = sockPtr->s_domain.d_consaddr(addrLen);
-    memcpy((void*) Data_custom_val(saVal), buffer, addrLen);
-    CAMLreturn(saVal);
+    sxVal = sockPtr->s_domain.d_consaddr(saPtr, addrLen);
+    CAMLreturn(sxVal);
 }
 
 /*---
 CAMLprim value cf_socket_getpeername(value sockVal)
 {
     CAMLparam1(sockVal);
-    CAMLlocal1(saVal);
+    CAMLlocal1(sxVal);
 
     const Cf_socket_t* sockPtr;
-    char buffer[SOCK_MAXADDRLEN];
+    struct sockaddr_storage ss;
+    struct sockaddr* saPtr;
     int addrLen, v;
     
     sockPtr = Cf_socket_val(sockVal);
-    addrLen = sockPtr->s_domain.d_socklen;
-    v = getpeername(sockPtr->s_fd, (struct sockaddr*) buffer, &addrLen);
+    saPtr = (struct sockaddr*) &ss;
+    addrLen = sizeof ss;
+    v = getpeername(sockPtr->s_fd, saPtr, &addrLen);
     if (v == -1) uerror("getpeername", Nothing);
         
-    saVal = sockPtr->s_domain.d_consaddr(addrLen);
-    memcpy((void*) Data_custom_val(saVal), buffer, addrLen);
-    CAMLreturn(saVal);
+    sxVal = sockPtr->s_domain.d_consaddr(saPtr, addrLen);
+    CAMLreturn(sxVal);
 }
 
 /*---
     external bind: ('af,'st) t -> 'af sockaddr_t -> unit = "cf_socket_bind"
   ---*/
-CAMLprim void cf_socket_bind(value sockVal, value saVal)
+CAMLprim void cf_socket_bind(value sockVal, value sxVal)
 {
-    CAMLparam2(sockVal, saVal);
+    CAMLparam2(sockVal, sxVal);
     
     const Cf_socket_t* sockPtr;
-    const struct sockaddr* saPtr;
+    const Cf_socket_sockaddrx_unit_t* sxPtr;
     
     sockPtr = Cf_socket_val(sockVal);
-    saPtr = (const struct sockaddr*) Data_custom_val(saVal);
-    if (bind(sockPtr->s_fd, saPtr, saPtr->sa_len)) uerror("bind", Nothing);
+    sxPtr = Cf_socket_sockaddrx_unit_val(sxVal);
+    if (bind(sockPtr->s_fd, &sxPtr->sx_sockaddr, sxPtr->sx_socklen))
+        uerror("bind", Nothing);
     
     CAMLreturn0;
 }
     external connect:
         ('af,'st) t -> 'af sockaddr_t -> unit = "cf_socket_connect"
   ---*/
-CAMLprim void cf_socket_connect(value sockVal, value saVal)
+CAMLprim void cf_socket_connect(value sockVal, value sxVal)
 {
-    CAMLparam2(sockVal, saVal);
+    CAMLparam2(sockVal, sxVal);
     
     const Cf_socket_t* sockPtr;
-    const struct sockaddr* saPtr;
+    const Cf_socket_sockaddrx_unit_t* sxPtr;
     int result, error;
     
     sockPtr = Cf_socket_val(sockVal);
-    saPtr = (const struct sockaddr*) Data_custom_val(saVal);
+    sxPtr = Cf_socket_sockaddrx_unit_val(sxVal);
     
     enter_blocking_section();
-    result = connect(sockPtr->s_fd, saPtr, saPtr->sa_len);
+    result = connect(sockPtr->s_fd, &sxPtr->sx_sockaddr, sxPtr->sx_socklen);
     error = errno;
     leave_blocking_section();
     
 CAMLprim value cf_socket_accept(value sockVal)
 {
     CAMLparam1(sockVal);
-    CAMLlocal3(newSockVal, saVal, resultVal);
+    CAMLlocal3(newSockVal, sxVal, resultVal);
 
     const Cf_socket_t* sockPtr;
-    char buffer[SOCK_MAXADDRLEN];
+    struct sockaddr_storage ss;
+    struct sockaddr* saPtr;
     int addrLen, newFd, error;
     
     sockPtr = Cf_socket_val(sockVal);
-    addrLen = sizeof buffer;
+    saPtr = (struct sockaddr*) &ss;
+    addrLen = sizeof ss;
     
     enter_blocking_section();
-    newFd = accept(sockPtr->s_fd, (struct sockaddr*) buffer, &addrLen);
+    newFd = accept(sockPtr->s_fd, saPtr, &addrLen);
     error = errno;
     leave_blocking_section();
     
     if (newFd == -1) unix_error(error, "accept", Nothing);
     
-    saVal = sockPtr->s_domain.d_consaddr(addrLen);
-    memcpy((void*) Data_custom_val(saVal), buffer, addrLen);
+    sxVal = sockPtr->s_domain.d_consaddr(saPtr, addrLen);
 
     newSockVal = cf_socket_alloc
        (newFd, sockPtr->s_socktype, sockPtr->s_protocol, &sockPtr->s_domain);
     
     resultVal = alloc_small(2, 0);
     Field(resultVal, 0) = newSockVal;
-    Field(resultVal, 1) = saVal;
+    Field(resultVal, 1) = sxVal;
     
     CAMLreturn(resultVal);
 }
   ---*/
 CAMLprim value cf_socket_sendto_native
    (value sockVal, value dataVal, value posVal, value lenVal,
-    value flagsVal, value saVal)
+    value flagsVal, value sxVal)
 {
     CAMLparam5(sockVal, dataVal, posVal, lenVal, flagsVal);
-    CAMLxparam1(saVal);
+    CAMLxparam1(sxVal);
     
     const Cf_socket_t* sockPtr;
     const char* dataPtr;
     int fd, pos, len, flags, result, error;
-    const struct sockaddr* saPtr;
+    const Cf_socket_sockaddrx_unit_t* sxPtr;
     
     sockPtr = Cf_socket_val(sockVal);
     dataPtr = String_val(dataVal);
     pos = Int_val(posVal);
     len = Int_val(lenVal);
     flags = cf_socket_msg_flags_to_int(flagsVal);
-    saPtr = (const struct sockaddr*) Data_custom_val(saVal);
+    sxPtr = Cf_socket_sockaddrx_unit_val(sxVal);
     
     enter_blocking_section();
-    result = sendto
-       (sockPtr->s_fd, dataPtr + pos, len, flags, saPtr, saPtr->sa_len);
+    result = sendto(sockPtr->s_fd, dataPtr + pos, len, flags,
+        &sxPtr->sx_sockaddr, sxPtr->sx_socklen);
     error = errno;
     leave_blocking_section();
     
     value flagsVal)
 {
     CAMLparam5(sockVal, dataVal, posVal, lenVal, flagsVal);
-    CAMLlocal2(saVal, resultVal);
+    CAMLlocal2(sxVal, resultVal);
     
     const Cf_socket_t* sockPtr;
     char* dataPtr;
     int fd, pos, len, flags, result, error;
-    char buffer[SOCK_MAXADDRLEN];
+    struct sockaddr_storage ss;
+    struct sockaddr* saPtr;
     int addrLen;
     
     sockPtr = Cf_socket_val(sockVal);
     pos = Int_val(posVal);
     len = Int_val(lenVal);
     flags = cf_socket_msg_flags_to_int(flagsVal);
-    addrLen = 0;
+    saPtr = (struct sockaddr*) &ss;
+    addrLen = sizeof ss;
 
     enter_blocking_section();
-    result = recvfrom
-       (sockPtr->s_fd, dataPtr + pos, len, flags, (struct sockaddr*) buffer,
+    result = recvfrom(sockPtr->s_fd, dataPtr + pos, len, flags, saPtr,
         &addrLen);
     error = errno;
     leave_blocking_section();
     
     if (result < 0) unix_error(error, "recvfrom", Nothing);
     
-    saVal = sockPtr->s_domain.d_consaddr(addrLen);
-    memcpy((void*) Data_custom_val(saVal), buffer, addrLen);
+    sxVal = sockPtr->s_domain.d_consaddr(saPtr, addrLen);
 
     resultVal = alloc_small(2, 0);
     Field(resultVal, 0) = Val_int(result);
-    Field(resultVal, 1) = saVal;
+    Field(resultVal, 1) = sxVal;
     
     CAMLreturn(resultVal);
 }
     size_t optlen)
 {
     int result;
+
     result = setsockopt
        (contextPtr->xopt_fd, contextPtr->xopt_level, contextPtr->xopt_name,
         optval, (int) optlen);
     const Cf_socket_option_t** optPtrPtr;
     const Cf_socket_t* sockPtr;
     Cf_socket_option_context_t xopt;
+    Cf_socket_getsockopt_f getF;
     
     sockPtr = Cf_socket_val(sockVal);
     optPtrPtr = Cf_socket_option_val(optVal);
+    getF = (*optPtrPtr)->opt_get;
+    if (!getF) {
+	char failStr[80];
+	sprintf(failStr, "Cf_socket.getsockopt %s not implemented.",
+		(*optPtrPtr)->opt_name_str);
+	failwith(failStr);
+    }
     xopt.xopt_fd = sockPtr->s_fd;
     xopt.xopt_level = (*optPtrPtr)->opt_level;
     xopt.xopt_name = (*optPtrPtr)->opt_name;
-    resultVal = (*optPtrPtr)->opt_get(&xopt);
+    resultVal = getF(&xopt);
     
     CAMLreturn(resultVal);
 }
 
-
 /*---
     external setsockopt:
         ('af,'st) t -> 'v untagged_sockopt_t -> 'v -> unit =
     const Cf_socket_option_t** optPtrPtr;
     const Cf_socket_t* sockPtr;
     Cf_socket_option_context_t xopt;
+    Cf_socket_setsockopt_f setF;
     
     sockPtr = Cf_socket_val(sockVal);
     optPtrPtr = Cf_socket_option_val(optVal);
+    setF = (*optPtrPtr)->opt_set;
+    if (!setF) {
+	char failStr[80];
+	sprintf(failStr, "Cf_socket.getsockopt %s not implemented.",
+		(*optPtrPtr)->opt_name_str);
+	failwith(failStr);
+    }
     xopt.xopt_fd = sockPtr->s_fd;
     xopt.xopt_level = (*optPtrPtr)->opt_level;
     xopt.xopt_name = (*optPtrPtr)->opt_name;
-    (*optPtrPtr)->opt_set(&xopt, setVal);
+    setF(&xopt, setVal);
     
     CAMLreturn0;
 }
 
-struct cf_socket_sockopt_lift_s {
-    value			ol_val;
-    const Cf_socket_option_t	ol_option;
-};
-
-typedef struct cf_socket_sockopt_lift_s Cf_socket_sockopt_lift_t;
-    
+/*---
+    type sockopt_index_t =
+        SO_DEBUG | SO_REUSEADDR | SO_REUSEPORT | SO_KEEPALIVE | SO_DONTROUTE |
+        SO_LINGER | SO_BROADCAST | SO_OOBINLINE | SO_SNDBUF | SO_RCVBUF |
+        SO_SNDLOWAT | SO_RCVLOWAT | SO_SNDTIMEO | SO_RCVTIMEO | SO_ERROR |
+        SO_NOSIGPIPE
+  ---*/
 static Cf_socket_sockopt_lift_t cf_socket_sockopt_lift_array[] = {
     { /* SO_DEBUG */
         Val_unit,
         }
     },
 
+#ifdef SO_REUSEPORT
     { /* SO_REUSEPORT */
         Val_unit,
         {
             cf_socket_getsockopt_bool, cf_socket_setsockopt_bool
         }
     },
+#else
+    { /* SO_REUSEPORT */
+        Val_unit, { }
+    },
+#endif
 
     { /* SO_KEEPALIVE */
         Val_unit,
         }
     },
 
+#ifdef SO_NOSIGPIPE
     { /* SO_NOSIGPIPE */
         Val_unit,
         {
             cf_socket_getsockopt_bool, cf_socket_setsockopt_bool
         }
     }
+#else
+    { /* SO_NOSIGPIPE */
+        Val_unit, { }
+    }
+#endif
 };
 
 #define CF_SOCKET_SOCKOPT_LIFT_ARRAY_SIZE \
         sizeof cf_socket_sockopt_lift_array[0])
 
 /*---
-    type sockopt_index_t =
-        SO_DEBUG | SO_REUSEADDR | SO_REUSEPORT | SO_KEEPALIVE | SO_DONTROUTE |
-        SO_LINGER | SO_BROADCAST | SO_OOBINLINE | SO_SNDBUF | SO_RCVBUF |
-        SO_SNDLOWAT | SO_RCVLOWAT | SO_SNDTIMEO | SO_RCVTIMEO | SO_ERROR |
-        SO_NOSIGPIPE
-    
     external sockopt_lift:
-        sockopt_index_t -> 'a untagged_sockopt_t = "cf_socket_sockopt_lift"
+        sockopt_index_t -> ('a, 'b, 'c) sockopt_t = "cf_socket_sockopt_lift"
   ---*/
 CAMLprim value cf_socket_sockopt_lift(value indexVal)
 {
 CAMLprim value cf_socket_init(value unit)
 {
     int i;
-        
+    
     register_custom_operations(&cf_socket_op);
     register_custom_operations(&cf_socket_option_op);