DBD-cubrid

 view release on metacpan or  search on metacpan

cci-src/src/cci/cci_network.c  view on Meta::CPAN

#include <fcntl.h>
#include <errno.h>

#if defined(WINDOWS)
#include <winsock2.h>
#include <windows.h>
#include <io.h>
#else
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <sys/time.h>
#include <poll.h>
#endif

/************************************************************************
 * OTHER IMPORTED HEADER FILES						*
 ************************************************************************/

#include "cci_common.h"
#include "cas_cci.h"
#include "cci_log.h"
#include "cci_network.h"
#include "cas_protocol.h"
#include "cci_query_execute.h"
#include "cci_util.h"
#if defined(WINDOWS)
#include "version.h"
#endif

/************************************************************************
 * PRIVATE DEFINITIONS							*
 ************************************************************************/

#define WRITE_TO_SOCKET(SOCKFD, MSG, SIZE)	\
	send(SOCKFD, MSG, SIZE, 0)
#define READ_FROM_SOCKET(SOCKFD, MSG, SIZE)	\
	recv(SOCKFD, MSG, SIZE, 0)

#define SOCKET_TIMEOUT 5000	/* msec */

/************************************************************************
 * PRIVATE TYPE DEFINITIONS						*
 ************************************************************************/

/************************************************************************
 * PRIVATE FUNCTION PROTOTYPES						*
 ************************************************************************/

static int connect_srv (unsigned char *ip_addr, int port, char is_retry, SOCKET * ret_sock, int login_timeout);
#if defined(ENABLE_UNUSED_FUNCTION)
static int net_send_int (SOCKET sock_fd, int value);
#endif
static int net_recv_int (SOCKET sock_fd, int port, int *value);
static int net_recv_stream (SOCKET sock_fd, int port, char *buf, int size, int timeout);
static int net_send_stream (SOCKET sock_fd, char *buf, int size);
static void init_msg_header (MSG_HEADER * header);
static int net_send_msg_header (SOCKET sock_fd, MSG_HEADER * header);
static int net_recv_msg_header (SOCKET sock_fd, int port, MSG_HEADER * header, int timeout);
static bool net_peer_socket_alive (SOCKET sd, int port, int timeout_msec);
static int net_cancel_request_internal (unsigned char *ip_addr, int port, char *msg, int msglen);
static int net_cancel_request_w_local_port (unsigned char *ip_addr, int port, int pid, unsigned short local_port);
static int net_cancel_request_wo_local_port (unsigned char *ip_addr, int port, int pid);

/************************************************************************
 * INTERFACE VARIABLES							*
 ************************************************************************/
/************************************************************************
 * PUBLIC VARIABLES							*
 ************************************************************************/
#if defined(CCI_OLEDB) || defined(CCI_ODBC)
static char cci_client_type = CAS_CLIENT_ODBC;
#else
static char cci_client_type = CAS_CLIENT_CCI;
#endif

/************************************************************************
 * PRIVATE VARIABLES							*
 ************************************************************************/

/************************************************************************
 * IMPLEMENTATION OF INTERFACE FUNCTIONS 				*
 ************************************************************************/

/************************************************************************
 * IMPLEMENTATION OF PUBLIC FUNCTIONS	 				*
 ************************************************************************/

int
net_connect_srv (T_CON_HANDLE * con_handle, int host_id, T_CCI_ERROR * err_buf, int login_timeout)
{
  SOCKET srv_sock_fd;
  char client_info[SRV_CON_CLIENT_INFO_SIZE];
  char db_info[SRV_CON_DB_INFO_SIZE];
  char ver_str[SRV_CON_VER_STR_MAX_SIZE];
  MSG_HEADER msg_header;
  int err_code, ret_value;
  int err_indicator;
  int new_port;
  char *msg_buf, *info, *p, *ver_ptr;
  unsigned char *ip_addr;
  int port;
  int body_len;
  T_BROKER_VERSION broker_ver;

  init_msg_header (&msg_header);

  memset (client_info, 0, sizeof (client_info));
  memset (db_info, 0, sizeof (db_info));

  strncpy (client_info, SRV_CON_CLIENT_MAGIC_STR, SRV_CON_CLIENT_MAGIC_LEN);
  client_info[SRV_CON_MSG_IDX_CLIENT_TYPE] = cci_client_type;
  client_info[SRV_CON_MSG_IDX_PROTO_VERSION] = CAS_PROTO_PACK_CURRENT_NET_VER;
  client_info[SRV_CON_MSG_IDX_FUNCTION_FLAG] = BROKER_RENEWED_ERROR_CODE | BROKER_SUPPORT_HOLDABLE_RESULT;
  client_info[SRV_CON_MSG_IDX_RESERVED2] = 0;

  info = db_info;
  if (con_handle->db_name)
    {
      strncpy (info, con_handle->db_name, SRV_CON_DBNAME_SIZE);

cci-src/src/cci/cci_network.c  view on Meta::CPAN


	      if (hm_broker_reconnect_when_server_down (con_handle)
		  && (con_handle->cas_info[CAS_INFO_ADDITIONAL_FLAG] & CAS_INFO_FLAG_MASK_NEW_SESSION_ID))
		{
		  char *p;

		  p = tmp_p + CAS_PROTOCOL_ERR_MSG_INDEX + err_msg_size - DRIVER_SESSION_SIZE;

		  memcpy (con_handle->session_id.id, p, DRIVER_SESSION_SIZE);
		  err_msg_size -= DRIVER_SESSION_SIZE;
		}

	      if (err_buf)
		{
		  memcpy (err_buf->err_msg, tmp_p + CAS_PROTOCOL_ERR_MSG_INDEX, err_msg_size);
		  err_buf->err_code = err_code;
		}
	      err_code = CCI_ER_DBMS;
	    }
	  FREE_MEM (tmp_p);
	  return err_code;
	}
    }
  else
    {
      assert (con_handle->cas_info[0] != 0 || con_handle->cas_info[1] != 0 || con_handle->cas_info[2] != 0
	      || con_handle->cas_info[3] != 0);
    }

  if (msg)
    {
      *msg = tmp_p;
    }
  else
    {
      FREE_MEM (tmp_p);
    }

  if (msg_size)
    {
      *msg_size = *(recv_msg_header.msg_body_size_ptr);
    }

  return result_code;

error_return:
  FREE_MEM (tmp_p);
  CLOSE_SOCKET (con_handle->sock_fd);
  con_handle->sock_fd = INVALID_SOCKET;

  return result_code;
}

int
net_recv_msg (T_CON_HANDLE * con_handle, char **msg, int *msg_size, T_CCI_ERROR * err_buf)
{
  return net_recv_msg_timeout (con_handle, msg, msg_size, err_buf, 0);
}

bool
net_peer_alive (unsigned char *ip_addr, int port, int timeout_msec)
{
  SOCKET sock_fd;
  int ret, dummy;
  const char *ping_msg = "PING_TEST!";

  if (connect_srv (ip_addr, port, 0, &sock_fd, timeout_msec) != CCI_ER_NO_ERROR)
    {
      CLOSE_SOCKET (sock_fd);
      return false;
    }

send_again:
  ret = WRITE_TO_SOCKET (sock_fd, ping_msg, strlen (ping_msg));
  if (ret < 0)
    {
      if (errno == EAGAIN)
	{
	  SLEEP_MILISEC (0, 1);
	  goto send_again;
	}
      else
	{
	  CLOSE_SOCKET (sock_fd);
	  return false;
	}
    }

recv_again:
  ret = READ_FROM_SOCKET (sock_fd, (char *) &dummy, sizeof (int));
  if (ret < 0)
    {
      if (errno == EAGAIN)
	{
	  SLEEP_MILISEC (0, 1);
	  goto recv_again;
	}
      else
	{
	  CLOSE_SOCKET (sock_fd);
	  return false;
	}
    }

  CLOSE_SOCKET (sock_fd);

  return true;
}

bool
net_check_broker_alive (unsigned char *ip_addr, int port, int timeout_msec)
{
  SOCKET sock_fd;
  MSG_HEADER msg_header;
  char client_info[SRV_CON_CLIENT_INFO_SIZE];
  char db_info[SRV_CON_DB_INFO_SIZE];
  char db_name[SRV_CON_DBNAME_SIZE];
  char url[SRV_CON_URL_SIZE];
  char *info;
  int err_code, ret_value;
  bool result = false;

  init_msg_header (&msg_header);

  memset (client_info, 0, sizeof (client_info));
  memset (db_info, 0, sizeof (db_info));

  strncpy (client_info, SRV_CON_CLIENT_MAGIC_STR, SRV_CON_CLIENT_MAGIC_LEN);
  client_info[SRV_CON_MSG_IDX_CLIENT_TYPE] = cci_client_type;
  client_info[SRV_CON_MSG_IDX_PROTO_VERSION] = CAS_PROTO_PACK_CURRENT_NET_VER;
  client_info[SRV_CON_MSG_IDX_FUNCTION_FLAG] = BROKER_RENEWED_ERROR_CODE;
  client_info[SRV_CON_MSG_IDX_RESERVED2] = 0;

  snprintf (db_name, SRV_CON_DBNAME_SIZE, HEALTH_CHECK_DUMMY_DB);
  snprintf (url, SRV_CON_URL_SIZE, "cci:cubrid:%s:%d:%s::********:", ip_addr, port, db_name);

  info = db_info;

  strncpy (info, db_name, SRV_CON_DBNAME_SIZE - 1);
  info += (SRV_CON_DBNAME_SIZE + SRV_CON_DBUSER_SIZE + SRV_CON_DBPASSWD_SIZE);

  strncpy (info, url, SRV_CON_URL_SIZE - 1);

  if (connect_srv (ip_addr, port, 0, &sock_fd, timeout_msec) < 0)
    {
      return false;
    }

  if (net_send_stream (sock_fd, client_info, SRV_CON_CLIENT_INFO_SIZE) < 0)
    {
      goto finish_health_check;
    }

  ret_value = net_recv_stream (sock_fd, port, (char *) &err_code, 4, timeout_msec);
  if (ret_value < 0)
    {
      goto finish_health_check;
    }

  err_code = ntohl (err_code);
  if (err_code < 0)
    {
      goto finish_health_check;
    }

  if (net_send_stream (sock_fd, db_info, SRV_CON_DB_INFO_SIZE) < 0)
    {
      goto finish_health_check;
    }

  if (net_recv_msg_header (sock_fd, port, &msg_header, timeout_msec) < 0)

cci-src/src/cci/cci_network.c  view on Meta::CPAN

  struct timeval tv;
#else
  struct pollfd po[1] = { {0, 0, 0} };
  int polling_timeout;
#endif
  int n;

  while (tot_read_len < size)
    {
#if defined(WINDOWS)
      FD_ZERO (&rfds);
      FD_SET (sock_fd, &rfds);

      if (timeout <= 0 || timeout > SOCKET_TIMEOUT)
	{
	  tv.tv_sec = SOCKET_TIMEOUT / 1000;
	  tv.tv_usec = (SOCKET_TIMEOUT % 1000) * 1000;
	}
      else
	{
	  tv.tv_sec = timeout / 1000;
	  tv.tv_usec = (timeout % 1000) * 1000;
	}

      n = select (sock_fd + 1, &rfds, NULL, NULL, &tv);

#else
      po[0].fd = sock_fd;
      po[0].events = POLLIN;

      if (timeout <= 0 || timeout > SOCKET_TIMEOUT)
	{
	  polling_timeout = SOCKET_TIMEOUT;
	}
      else
	{
	  polling_timeout = timeout;
	}

      n = poll (po, 1, polling_timeout);

#endif

      if (n == 0)
	{
	  /* select / poll return time out */
	  if (timeout > 0)
	    {
	      timeout -= SOCKET_TIMEOUT;
	      if (timeout <= 0)
		{
		  assert (tot_read_len == 0 || size == tot_read_len);
		  return CCI_ER_QUERY_TIMEOUT;
		}
	      else
		{
		  continue;
		}
	    }

	  if (net_peer_socket_alive (sock_fd, port, SOCKET_TIMEOUT) == true)
	    {
	      continue;
	    }
	  else
	    {
	      return CCI_ER_COMMUNICATION;
	    }
	}
      else if (n < 0)
	{
	  /* select / poll return error */
	  if (errno == EINTR)
	    {
	      continue;
	    }

	  return CCI_ER_COMMUNICATION;
	}
#if !defined (WINDOWS)
      else if (po[0].revents & POLLERR || po[0].revents & POLLHUP)
	{
	  po[0].revents = 0;
	  return CCI_ER_COMMUNICATION;
	}
#endif /* !WINDOWS */

      read_len = READ_FROM_SOCKET (sock_fd, buf + tot_read_len, size - tot_read_len);
      if (read_len <= 0)
	{
	  return CCI_ER_COMMUNICATION;
	}

      tot_read_len += read_len;
    }

  return 0;
}

static bool
net_peer_socket_alive (SOCKET sd, int port, int timeout_msec)
{
  unsigned char ip_addr[4];
  struct sockaddr_in saddr;
  socklen_t slen;

  slen = sizeof (saddr);
  if (getpeername (sd, (struct sockaddr *) &saddr, &slen) < 0)
    {
      return false;
    }

  /* if Unix domain socket, the peer(=local) is alive always */
  if (saddr.sin_family != AF_INET)
    {
      return true;
    }

  memcpy (ip_addr, &saddr.sin_addr, 4);

  return net_peer_alive (ip_addr, port, timeout_msec);
}

static int
net_recv_msg_header (SOCKET sock_fd, int port, MSG_HEADER * header, int timeout)
{
  int result_code;

  result_code = net_recv_stream (sock_fd, port, header->buf, MSG_HEADER_SIZE, timeout);

  if (result_code < 0)
    {
      return result_code;
    }
  *(header->msg_body_size_ptr) = ntohl (*(header->msg_body_size_ptr));

  assert (header->info_ptr[0] != 0 || header->info_ptr[1] != 0 || header->info_ptr[2] != 0 || header->info_ptr[3] != 0);
  if (*(header->msg_body_size_ptr) < 0)
    {
      return CCI_ER_COMMUNICATION;
    }
  return 0;
}

static int
net_send_msg_header (SOCKET sock_fd, MSG_HEADER * header)
{
  *(header->msg_body_size_ptr) = htonl (*(header->msg_body_size_ptr));
  if (net_send_stream (sock_fd, header->buf, MSG_HEADER_SIZE) < 0)
    {
      return CCI_ER_COMMUNICATION;
    }

  return 0;
}

static int
net_send_stream (SOCKET sock_fd, char *msg, int size)
{
  int write_len;
  while (size > 0)
    {
      write_len = WRITE_TO_SOCKET (sock_fd, msg, size);
      if (write_len <= 0)
	{
	  return CCI_ER_COMMUNICATION;
	}
      msg += write_len;
      size -= write_len;
    }
  return 0;
}

static void
init_msg_header (MSG_HEADER * header)
{
  header->msg_body_size_ptr = (int *) (header->buf);
  header->info_ptr = (char *) (header->buf + MSG_HEADER_MSG_SIZE);

  *(header->msg_body_size_ptr) = 0;
  header->info_ptr[0] = CAS_INFO_STATUS_ACTIVE;



( run in 0.983 second using v1.01-cache-2.11-cpan-39bf76dae61 )