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 )