mturk       2005/06/30 08:19:15

  Added:       jni/native/os/unix uxpipe.c
  Log:
  Add AF_UNIX network interface implementation.
  
  Revision  Changes    Path
  1.1                  jakarta-tomcat-connectors/jni/native/os/unix/uxpipe.c
  
  Index: uxpipe.c
  ===================================================================
  /* Copyright 2000-2004 The Apache Software Foundation
   *
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   *
   *     http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
  
  /** UNIX AF_LOCAL network wrapper
   *
   * @author Mladen Turk
   * @version $Revision: 1.1 $, $Date: 2005/06/30 15:19:15 $
   */
  
  
  #include "tcn.h"
  #include "apr_thread_mutex.h"
  #include "apr_poll.h"
  
  /* ### should be tossed in favor of APR */
  #include <sys/stat.h>
  #include <sys/un.h> /* for sockaddr_un */
  
  #ifdef TCN_DO_STATISTICS
  #include "apr_atomic.h"
  
  static volatile apr_uint32_t uxp_created  = 0;
  static volatile apr_uint32_t uxp_closed   = 0;
  static volatile apr_uint32_t uxp_cleared  = 0;
  static volatile apr_uint32_t uxp_accepted = 0;
  
  void uxp_network_dump_statistics()
  {
      fprintf(stderr, "NT Network Statistics ..\n");
      fprintf(stderr, "Sockets created         : %d\n", uxp_created);
      fprintf(stderr, "Sockets accepted        : %d\n", uxp_accepted);
      fprintf(stderr, "Sockets closed          : %d\n", uxp_closed);
      fprintf(stderr, "Sockets cleared         : %d\n", uxp_cleared);
  }
  
  #endif
  
  #define DEFNAME     "/var/run/tomcatnativesock"
  #define DEFNAME_FMT "/var/run/tomcatnativesock%08x%08x"
  #define DEFSIZE     8192
  #define DEFTIMEOUT  60000
  
  #define TCN_UXP_UNKNOWN     0
  #define TCN_UXP_CLIENT      1
  #define TCN_UXP_ACCEPTED    2
  #define TCN_UXP_SERVER      3
  
  #define TCN_UNIX_MAXPATH    1024
  typedef struct {
      apr_pool_t          *pool;
      apr_socket_t        *sock;               /* APR socket */
      int                 sd;
      struct sockaddr_un  uxaddr;
      int                 timeout;
      int                 mode;                 /* Client or server mode */
      char                name[TCN_UNIX_MAXPATH+1];
  } tcn_uxp_conn_t;
  
  static apr_status_t APR_THREAD_FUNC
  uxp_socket_timeout_set(apr_socket_t *sock, apr_interval_time_t t)
  {
      tcn_uxp_conn_t *con = (tcn_uxp_conn_t *)sock;
      if (t < 0)
          con->timeout = -1;
      else
          con->timeout = (int)(apr_time_as_msec(t));
      return APR_SUCCESS;
  }
  
  static apr_status_t APR_THREAD_FUNC
  uxp_socket_timeout_get(apr_socket_t *sock, apr_interval_time_t *t)
  {
      tcn_uxp_conn_t *con = (tcn_uxp_conn_t*)sock;
      if (con->timeout < 0)
          *t = -1;
      else
          *t = con->timeout * 1000;
      return APR_SUCCESS;
  }
  
  static APR_INLINE apr_status_t APR_THREAD_FUNC
  uxp_socket_opt_set(apr_socket_t *sock, apr_int32_t opt, apr_int32_t on)
  {
      tcn_uxp_conn_t *con = (tcn_uxp_conn_t *)sock;
      return apr_socket_opt_set(con->sock, opt, on);
  }
  
  static APR_INLINE apr_status_t APR_THREAD_FUNC
  uxp_socket_opt_get(apr_socket_t *sock, apr_int32_t opt, apr_int32_t *on)
  {
      tcn_uxp_conn_t *con = (tcn_uxp_conn_t *)sock;
      return apr_socket_opt_get(con->sock, opt, on);
  }
  
  static apr_status_t uxp_cleanup(void *data)
  {
      tcn_uxp_conn_t *con = (tcn_uxp_conn_t *)data;
  
      if (con) {
          if (con->sock) {
              apr_socket_close(con->sock);
              con->sock = NULL;
          }
          if (con->mode == TCN_UXP_SERVER) {
              unlink(con->name);
              con->mode = TCN_UXP_UNKNOWN;
          }
      }
  
  #ifdef TCN_DO_STATISTICS
      apr_atomic_inc32(&uxp_cleared);
  #endif
      return APR_SUCCESS;
  }
  
  static apr_status_t APR_THREAD_FUNC
  uxp_socket_shutdown(apr_socket_t *sock, apr_shutdown_how_e how)
  {
      tcn_uxp_conn_t *con = (tcn_uxp_conn_t *)sock;
      return apr_socket_shutdown(con->sock, how);
  }
  
  static apr_status_t APR_THREAD_FUNC
  uxp_socket_close(apr_socket_t *sock)
  {
  #ifdef TCN_DO_STATISTICS
      apr_atomic_inc32(&uxp_closed);
  #endif
      return uxp_cleanup(sock);
  }
  
  static apr_status_t APR_THREAD_FUNC
  uxp_socket_recv(apr_socket_t *sock, char *buf, apr_size_t *len)
  {
      tcn_uxp_conn_t *con = (tcn_uxp_conn_t *)sock;
      return apr_socket_recv(con->sock, buf, len);
  }
  
  
  static apr_status_t APR_THREAD_FUNC
  uxp_socket_send(apr_socket_t *sock, const char *buf,
                  apr_size_t *len)
  {
      tcn_uxp_conn_t *con = (tcn_uxp_conn_t *)sock;
      return apr_socket_send(con->sock, buf, len);
  }
  
  static apr_status_t APR_THREAD_FUNC
  uxp_socket_sendv(apr_socket_t *sock,
                   const struct iovec *vec,
                   apr_int32_t nvec, apr_size_t *len)
  {
      tcn_uxp_conn_t *con = (tcn_uxp_conn_t *)sock;
      return apr_socket_sendv(con->sock, vec, nvec, len);
  }
  
  static apr_status_t uxp_socket_cleanup(void *data)
  {
      tcn_socket_t *s = (tcn_socket_t *)data;
  
      if (s->cleanup) {
          (*s->cleanup)(s->opaque);
          s->cleanup = NULL;
      }
  #ifdef TCN_DO_STATISTICS
      apr_atomic_inc32(&uxp_cleared);
  #endif
      return APR_SUCCESS;
  }
  
  TCN_IMPLEMENT_CALL(jlong, Local, create)(TCN_STDARGS, jstring name,
                                           jlong pool)
  {
      apr_pool_t *p = J2P(pool, apr_pool_t *);
      tcn_socket_t   *s   = NULL;
      tcn_uxp_conn_t *con = NULL;
      int sd;
      TCN_ALLOC_CSTRING(name);
  
      UNREFERENCED(o);
      TCN_ASSERT(pool != 0);
  
      if ((sd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
          tcn_ThrowAPRException(e, apr_get_netos_error());
          return 0;
      }
  #ifdef TCN_DO_STATISTICS
      uxp_created++;
  #endif
      con = (tcn_uxp_conn_t *)apr_pcalloc(p, sizeof(tcn_uxp_conn_t));
      con->pool = p;
      con->mode = TCN_UXP_UNKNOWN;
      con->timeout = DEFTIMEOUT;
      con->sd = sd;
      con->uxaddr.sun_family = AF_UNIX;
      if (J2S(name)) {
          strcpy(con->uxaddr.sun_path, J2S(name));
          TCN_FREE_CSTRING(name);
      }
      else
          strcpy(con->uxaddr.sun_path, DEFNAME);
      s = (tcn_socket_t *)apr_pcalloc(p, sizeof(tcn_socket_t));
      s->pool     = p;
      s->type     = TCN_SOCKET_UNIX;
      s->cleanup  = uxp_cleanup;
      s->recv     = uxp_socket_recv;
      s->send     = uxp_socket_send;
      s->sendv    = uxp_socket_sendv;
      s->shutdown = uxp_socket_shutdown;
      s->tmget    = uxp_socket_timeout_get;
      s->tmset    = uxp_socket_timeout_set;
      s->close    = uxp_socket_close;
      s->opaque   = con;
      apr_pool_cleanup_register(p, (const void *)s,
                                uxp_socket_cleanup,
                                apr_pool_cleanup_null);
  
      apr_os_sock_put(&(con->sock), &(con->sd), p);
  
      return P2J(s);
  
  }
  
  TCN_IMPLEMENT_CALL(jint, Local, bind)(TCN_STDARGS, jlong sock,
                                        jlong sa)
  {
      tcn_socket_t *s = J2P(sock, tcn_socket_t *);
      UNREFERENCED_STDARGS;
      UNREFERENCED(sa);
      TCN_ASSERT(sock != 0);
      if (s->type == TCN_SOCKET_UNIX) {
          int rc;
          tcn_uxp_conn_t *c = (tcn_uxp_conn_t *)s->opaque;
          c->mode = TCN_UXP_SERVER;
          rc = bind(c->sd, (struct sockaddr *)&(c->uxaddr), sizeof(c->uxaddr));
          if (rc < 0)
              return errno;
          else
              return APR_SUCCESS;
      }
      else
          return APR_EINVAL;
  }
  
  TCN_IMPLEMENT_CALL(jint, Local, listen)(TCN_STDARGS, jlong sock,
                                          jint backlog)
  {
      tcn_socket_t *s = J2P(sock, tcn_socket_t *);
      UNREFERENCED_STDARGS;
  
      TCN_ASSERT(sock != 0);
      if (s->type == TCN_SOCKET_UNIX) {
          tcn_uxp_conn_t *c = (tcn_uxp_conn_t *)s->opaque;
          c->mode = TCN_UXP_SERVER;
          return apr_socket_listen(c->sock, (apr_int32_t)backlog);
      }
      else
          return APR_EINVAL;
  }
  
  TCN_IMPLEMENT_CALL(jlong, Local, accept)(TCN_STDARGS, jlong sock)
  {
      tcn_socket_t *s = J2P(sock, tcn_socket_t *);
      apr_pool_t   *p = NULL;
      tcn_socket_t *a = NULL;
      tcn_uxp_conn_t *con = NULL;
  
      UNREFERENCED(o);
      TCN_ASSERT(sock != 0);
  
      TCN_THROW_IF_ERR(apr_pool_create(&p, s->pool), p);
      if (s->type == TCN_SOCKET_UNIX) {
          apr_socklen_t len;
          tcn_uxp_conn_t *c = (tcn_uxp_conn_t *)s->opaque;
          con = (tcn_uxp_conn_t *)apr_pcalloc(p, sizeof(tcn_uxp_conn_t));
          con->pool = p;
          con->mode = TCN_UXP_ACCEPTED;
          con->timeout = c->timeout;
          len = sizeof(c->uxaddr);
          /* Block until a client connects */
          con->sd = accept(c->sd, (struct sockaddr *)&(con->uxaddr), &len);
          if (con->sd < 0) {
              tcn_ThrowAPRException(e, apr_get_os_error());
              goto cleanup;
          }
      }
      else {
          tcn_ThrowAPRException(e, APR_ENOTIMPL);
          goto cleanup;
      }
      if (con) {
  #ifdef TCN_DO_STATISTICS
          apr_atomic_inc32(&uxp_accepted);
  #endif
          a = (tcn_socket_t *)apr_pcalloc(p, sizeof(tcn_socket_t));
          a->pool = p;
          a->type     = TCN_SOCKET_NTPIPE;
          a->cleanup  = uxp_cleanup;
          a->recv     = uxp_socket_recv;
          a->send     = uxp_socket_send;
          a->sendv    = uxp_socket_sendv;
          a->shutdown = uxp_socket_shutdown;
          a->tmget    = uxp_socket_timeout_get;
          a->tmset    = uxp_socket_timeout_set;
          a->get      = uxp_socket_opt_get;
          a->set      = uxp_socket_opt_set;
          a->close    = uxp_socket_close;
          a->opaque   = con;
          apr_pool_cleanup_register(p, (const void *)a,
                                    uxp_socket_cleanup,
                                    apr_pool_cleanup_null);
          apr_os_sock_put(&(con->sock), &(con->sd), p);
      }
      return P2J(a);
  cleanup:
      if (p)
          apr_pool_destroy(p);
      return 0;
  }
  
  TCN_IMPLEMENT_CALL(jint, Local, connect)(TCN_STDARGS, jlong sock,
                                           jlong sa)
  {
      tcn_socket_t *s = J2P(sock, tcn_socket_t *);
      apr_pool_t   *p = NULL;
      tcn_socket_t *a = NULL;
      tcn_uxp_conn_t *con = NULL;
      int rc;
  
      UNREFERENCED(o);
      UNREFERENCED(sa);
      TCN_ASSERT(sock != 0);
      if (s->type != TCN_SOCKET_UNIX)
          return APR_ENOTSOCK;
      con = (tcn_uxp_conn_t *)s->opaque;
      if (con->mode != TCN_UXP_UNKNOWN)
          return APR_EINVAL;
      con->mode = TCN_UXP_CLIENT;
      do {
          rc = connect(con->sd, (const struct sockaddr *)&(con->uxaddr),
                       sizeof(con->uxaddr));
      } while (rc == -1 && errno == EINTR);
  
      if (rc == -1 && errno != EISCONN)
          return errno;
  
      return APR_SUCCESS;
  }
  
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to