/*
 * nasd_pipe_dce.c
 *
 * Byte-pipe gymnastics.
 *
 * Authors: Nat Lanza, Jim Zelenka
 */
/*
 * Copyright (c) of Carnegie Mellon University, 1999.
 *
 * Permission to reproduce, use, and prepare derivative works of
 * this software for internal use is granted provided the copyright
 * and "No Warranty" statements are included with all reproductions
 * and derivative works. This software may also be redistributed
 * without charge provided that the copyright and "No Warranty"
 * statements are included in all redistributions.
 *
 * NO WARRANTY. THIS SOFTWARE IS FURNISHED ON AN "AS IS" BASIS.
 * CARNEGIE MELLON UNIVERSITY MAKES NO WARRANTIES OF ANY KIND, EITHER
 * EXPRESSED OR IMPLIED AS TO THE MATTER INCLUDING, BUT NOT LIMITED
 * TO: WARRANTY OF FITNESS FOR PURPOSE OR MERCHANTABILITY, EXCLUSIVITY
 * OF RESULTS OR RESULTS OBTAINED FROM USE OF THIS SOFTWARE. CARNEGIE
 * MELLON UNIVERSITY DOES NOT MAKE ANY WARRANTY OF ANY KIND WITH RESPECT
 * TO FREEDOM FROM PATENT, TRADEMARK, OR COPYRIGHT INFRINGEMENT.
 */


#if defined(DEC_OSF) || (defined(OSF) && defined(MACH))
#include <sys/secdefines.h>
#if SEC_BASE > 0
#include <sys/security.h>
#include <sys/audit.h>
#include <sys/secpolicy.h>
#endif /* SEC_BASE */
#endif /* DEC_OSF || (OSF && MACH) */
#include <sys/errno.h>

#include <nasd/nasd_options.h>
#undef  NASD_PTHREAD_EXC
#define NASD_PTHREAD_EXC 1
#include <nasd/nasd_types.h>
#include <nasd/nasd_freelist.h>
#include <nasd/nasd_itypes.h>
#include <nasd/nasd_mem.h>
#include <nasd/nasd_sys.h>
#include <nasd/nasd_common.h>
#include <nasd/nasd_marshall.h>
#include <nasd/nasd_shutdown.h>

#include <nasd/nasd_pipe_dce.h>

#ifndef KERNEL
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <nasd/nasd_udppipe.h>
#endif /* !KERNEL */

#include <dce/dce_error.h>
#if defined(DEC_OSF) && defined(KERNEL)
#include <dce/ker/pthread_exc.h>
#endif /* DEC_OSF && KERNEL */
#include <rpc/rpc.h>
#include <dce/rpc.h>
#include <dce/stubbase.h>

#if defined(DEC_OSF) && defined(KERNEL)
/* I don't really want to use DCE's malloc and free */
#undef malloc
#undef free
#endif /* DEC_OSF && KERNEL */

#define NASD_OD_RPC_NASD_RET out_res.nasd_status
#include <nasd/nasd_od_rpc.h>

#if NASD_DRIVE_DISABLE_CONCURRENT_DCE_PIPES > 0
NASD_DECLARE_MUTEX(nasd_dce_pipe_lock)
#endif /* NASD_DRIVE_DISABLE_CONCURRENT_DCE_PIPES > 0 */

char nasd_pipe_bitbucket[NASD_OD_BASIC_BLOCKSIZE];

nasd_status_t
nasd_dcepipe_init(nasd_shutdown_list_t *shutdown_list)
{
  nasd_status_t rc;

#if NASD_DRIVE_DISABLE_CONCURRENT_DCE_PIPES > 0
  rc = nasd_mutex_init(&nasd_dce_pipe_lock);
  if (rc) {
    return(rc);
  }

  rc = nasd_shutdown_mutex(shutdown_list, &nasd_dce_pipe_lock);
  if (rc) {
    return(rc);
  }
#endif /* NASD_DRIVE_DISABLE_CONCURRENT_DCE_PIPES > 0 */

  return(NASD_SUCCESS);
}

nasd_status_t
nasd_dcepipe_push(
  void        *real_pipe,
  void        *buf,
  nasd_len_t   in_len)
{
  nasd_byte_pipe_t *byte_pipe;
  nasd_status_t rc;

#define CATCHPUSHPIPE(_exc_) \
 CATCH(_exc_) { \
   nasd_printf("DCE ex (%s) performing byte_pipe.push(0x%lx, 0x%lx, %d)\n", \
     NASD_STRING(_exc_), \
     (unsigned long)byte_pipe->state, (unsigned long)buf, \
     in_len); \
   rc = NASD_RPC_TRAP; \
 }

  byte_pipe = (nasd_byte_pipe_t *)real_pipe;

#if NASD_DRIVE_DISABLE_CONCURRENT_DCE_PIPES > 0
  NASD_LOCK_MUTEX(nasd_dce_pipe_lock);
#endif /* NASD_DRIVE_DISABLE_CONCURRENT_DCE_PIPES > 0 */

  TRY {
    byte_pipe->push(byte_pipe->state, buf, in_len);
    rc = NASD_SUCCESS;
  }
  CATCHPUSHPIPE(rpc_x_ss_char_trans_open_fail)
  CATCHPUSHPIPE(rpc_x_ss_char_trans_short_file)
  CATCHPUSHPIPE(rpc_x_ss_context_damaged)
  CATCHPUSHPIPE(rpc_x_ss_context_mismatch)
  CATCHPUSHPIPE(rpc_x_ss_in_null_context)
  CATCHPUSHPIPE(rpc_x_ss_pipe_closed)
  CATCHPUSHPIPE(rpc_x_ss_pipe_comm_error)
  CATCHPUSHPIPE(rpc_x_ss_pipe_discipline_error)
  CATCHPUSHPIPE(rpc_x_ss_pipe_empty)
  CATCHPUSHPIPE(rpc_x_ss_pipe_memory)
  CATCHPUSHPIPE(rpc_x_ss_pipe_order)
  CATCHPUSHPIPE(rpc_x_ss_remote_comm_failure)
  CATCHPUSHPIPE(rpc_x_ss_remote_no_memory)
  CATCHPUSHPIPE(rpc_x_ss_bad_buffer)
  CATCHPUSHPIPE(rpc_x_ss_bad_es_action)
  CATCHPUSHPIPE(rpc_x_ss_wrong_es_version)
  CATCHPUSHPIPE(rpc_x_stub_protocol_error)
  CATCHPUSHPIPE(rpc_x_unknown_stub_rtl_if_vers)
  CATCH_ALL {
    nasd_printf("DCE ex (other) performing byte_pipe.push(0x%lx, 0x%lx, %d)\n",
      (unsigned long)byte_pipe->state, (unsigned long)buf,
      in_len);
    rc = NASD_RPC_TRAP;
  } ENDTRY

#if NASD_DRIVE_DISABLE_CONCURRENT_DCE_PIPES > 0
  NASD_UNLOCK_MUTEX(nasd_dce_pipe_lock);
#endif /* NASD_DRIVE_DISABLE_CONCURRENT_DCE_PIPES > 0 */

  return(rc);
}

nasd_status_t
nasd_dcepipe_pull(
  void        *real_pipe,
  void        *buf,
  nasd_len_t   in_len,
  nasd_len_t  *out_lenp)
{
  nasd_byte_pipe_t *byte_pipe;
  idl_ulong_int count;
  nasd_status_t rc;

  byte_pipe = (nasd_byte_pipe_t *)real_pipe;

#define CATCHPULLPIPE(_exc_) \
 CATCH(_exc_) { \
   nasd_printf("DCE ex (%s) performing byte_pipe.pull(0x%lx, 0x%lx, %d, 0x%lx)\n", \
     NASD_STRING(_exc_), \
     (unsigned long)byte_pipe->state, (unsigned long)buf, \
     in_len, (unsigned long)&count); \
   *out_lenp = 0; \
   rc = NASD_RPC_TRAP; \
 }

#if NASD_DRIVE_DISABLE_CONCURRENT_DCE_PIPES > 0
  NASD_LOCK_MUTEX(nasd_dce_pipe_lock);
#endif /* NASD_DRIVE_DISABLE_CONCURRENT_DCE_PIPES > 0 */

  TRY {
    byte_pipe->pull(byte_pipe->state, (nasd_byte_t *)buf, in_len, &count);
    *out_lenp = count;
    rc = NASD_SUCCESS;
  }
  CATCHPULLPIPE(rpc_x_ss_char_trans_open_fail)
  CATCHPULLPIPE(rpc_x_ss_char_trans_short_file)
  CATCHPULLPIPE(rpc_x_ss_context_damaged)
  CATCHPULLPIPE(rpc_x_ss_context_mismatch)
  CATCHPULLPIPE(rpc_x_ss_in_null_context)
  CATCHPULLPIPE(rpc_x_ss_pipe_closed)
  CATCHPULLPIPE(rpc_x_ss_pipe_comm_error)
  CATCHPULLPIPE(rpc_x_ss_pipe_discipline_error)
  CATCHPULLPIPE(rpc_x_ss_pipe_empty)
  CATCHPULLPIPE(rpc_x_ss_pipe_memory)
  CATCHPULLPIPE(rpc_x_ss_pipe_order)
  CATCHPULLPIPE(rpc_x_ss_remote_comm_failure)
  CATCHPULLPIPE(rpc_x_ss_remote_no_memory)
  CATCHPULLPIPE(rpc_x_ss_bad_buffer)
  CATCHPULLPIPE(rpc_x_ss_bad_es_action)
  CATCHPULLPIPE(rpc_x_ss_wrong_es_version)
  CATCHPULLPIPE(rpc_x_stub_protocol_error)
  CATCHPULLPIPE(rpc_x_unknown_stub_rtl_if_vers)
  CATCH_ALL {
    nasd_printf("DCE ex (other) performing byte_pipe.pull(0x%lx, 0x%lx, %d, 0x%lx)\n",
      (unsigned long)byte_pipe->state, (unsigned long)buf,
      in_len, (unsigned long)&count);
    *out_lenp = 0;
    rc = NASD_RPC_TRAP;
  } ENDTRY

#if NASD_DRIVE_DISABLE_CONCURRENT_DCE_PIPES > 0
  NASD_UNLOCK_MUTEX(nasd_dce_pipe_lock);
#endif /* NASD_DRIVE_DISABLE_CONCURRENT_DCE_PIPES > 0 */

  return(rc);
}

nasd_status_t
nasd_dcepipe_drainpull(
  void        *real_pipe)
{
  nasd_len_t tcount;
  nasd_status_t rc;

  do {
    rc = nasd_dcepipe_pull(real_pipe, (nasd_byte_t *)nasd_pipe_bitbucket,
      NASD_OD_BASIC_BLOCKSIZE, &tcount);
  } while ((rc == NASD_SUCCESS) && tcount);

  return(rc);
}

nasd_status_t
nasd_dceprocpipe_push(void *real_pipe, void *buf, nasd_len_t in_len,
                      nasd_byte_t *ign1, nasd_byte_t *ign2, int *ign3)
{
  return nasd_dcepipe_push(real_pipe, buf, in_len);
}

/* Local Variables:  */
/* indent-tabs-mode: nil */
/* tab-width: 2 */
/* End: */
