mirror of
https://github.com/MariaDB/server.git
synced 2025-05-29 21:42:28 +03:00
Manual merge.
This commit is contained in:
parent
792d401981
commit
ab271b4d84
153
sql/net_serv.cc
153
sql/net_serv.cc
@ -14,6 +14,13 @@
|
|||||||
along with this program; if not, write to the Free Software
|
along with this program; if not, write to the Free Software
|
||||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||||
|
|
||||||
|
/*
|
||||||
|
This file is the net layer API for the MySQL client/server protocol,
|
||||||
|
which is a tightly coupled, proprietary protocol owned by MySQL AB.
|
||||||
|
Any re-implementations of this protocol must also be under GPL
|
||||||
|
unless one has got an license from MySQL AB stating otherwise.
|
||||||
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Write and read of logical packets to/from socket
|
Write and read of logical packets to/from socket
|
||||||
|
|
||||||
@ -26,6 +33,10 @@
|
|||||||
C file.
|
C file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
HFTODO this must be hidden if we don't want client capabilities in
|
||||||
|
embedded library
|
||||||
|
*/
|
||||||
#ifdef __WIN__
|
#ifdef __WIN__
|
||||||
#include <winsock.h>
|
#include <winsock.h>
|
||||||
#endif
|
#endif
|
||||||
@ -41,6 +52,13 @@
|
|||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
|
||||||
|
#ifdef EMBEDDED_LIBRARY
|
||||||
|
#undef MYSQL_SERVER
|
||||||
|
#undef MYSQL_CLIENT
|
||||||
|
#define MYSQL_CLIENT
|
||||||
|
#endif /*EMBEDDED_LIBRARY */
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
The following handles the differences when this is linked between the
|
The following handles the differences when this is linked between the
|
||||||
client and the server.
|
client and the server.
|
||||||
@ -66,10 +84,15 @@ void sql_print_error(const char *format,...);
|
|||||||
|
|
||||||
#ifdef MYSQL_SERVER
|
#ifdef MYSQL_SERVER
|
||||||
#define USE_QUERY_CACHE
|
#define USE_QUERY_CACHE
|
||||||
|
/*
|
||||||
|
The following variables/functions should really not be declared
|
||||||
|
extern, but as it's hard to include mysql_priv.h here, we have to
|
||||||
|
live with this for a while.
|
||||||
|
*/
|
||||||
extern uint test_flags;
|
extern uint test_flags;
|
||||||
extern void query_cache_insert(NET *net, const char *packet, ulong length);
|
|
||||||
extern ulong bytes_sent, bytes_received, net_big_packet_count;
|
extern ulong bytes_sent, bytes_received, net_big_packet_count;
|
||||||
extern pthread_mutex_t LOCK_bytes_sent , LOCK_bytes_received;
|
extern pthread_mutex_t LOCK_bytes_sent , LOCK_bytes_received;
|
||||||
|
extern void query_cache_insert(NET *net, const char *packet, ulong length);
|
||||||
#else
|
#else
|
||||||
#undef statistic_add
|
#undef statistic_add
|
||||||
#undef statistic_increment
|
#undef statistic_increment
|
||||||
@ -85,7 +108,7 @@ static my_bool net_write_buff(NET *net,const char *packet,ulong len);
|
|||||||
|
|
||||||
/* Init with packet info */
|
/* Init with packet info */
|
||||||
|
|
||||||
int my_net_init(NET *net, Vio* vio)
|
my_bool my_net_init(NET *net, Vio* vio)
|
||||||
{
|
{
|
||||||
DBUG_ENTER("my_net_init");
|
DBUG_ENTER("my_net_init");
|
||||||
my_net_local_init(net); /* Set some limits */
|
my_net_local_init(net); /* Set some limits */
|
||||||
@ -104,6 +127,7 @@ int my_net_init(NET *net, Vio* vio)
|
|||||||
net->where_b = net->remain_in_buf=0;
|
net->where_b = net->remain_in_buf=0;
|
||||||
net->last_errno=0;
|
net->last_errno=0;
|
||||||
net->query_cache_query=0;
|
net->query_cache_query=0;
|
||||||
|
net->report_error= 0;
|
||||||
|
|
||||||
if (vio != 0) /* If real connection */
|
if (vio != 0) /* If real connection */
|
||||||
{
|
{
|
||||||
@ -132,7 +156,7 @@ void net_end(NET *net)
|
|||||||
|
|
||||||
/* Realloc the packet buffer */
|
/* Realloc the packet buffer */
|
||||||
|
|
||||||
static my_bool net_realloc(NET *net, ulong length)
|
my_bool net_realloc(NET *net, ulong length)
|
||||||
{
|
{
|
||||||
uchar *buff;
|
uchar *buff;
|
||||||
ulong pkt_length;
|
ulong pkt_length;
|
||||||
@ -141,10 +165,11 @@ static my_bool net_realloc(NET *net, ulong length)
|
|||||||
|
|
||||||
if (length >= net->max_packet_size)
|
if (length >= net->max_packet_size)
|
||||||
{
|
{
|
||||||
DBUG_PRINT("error",("Packet too large. Max sixe: %lu",
|
DBUG_PRINT("error", ("Packet too large. Max size: %lu",
|
||||||
net->max_packet_size));
|
net->max_packet_size));
|
||||||
net->error=1;
|
net->error= 1;
|
||||||
net->last_errno=ER_NET_PACKET_TOO_LARGE;
|
net->report_error= 1;
|
||||||
|
net->last_errno= ER_NET_PACKET_TOO_LARGE;
|
||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
}
|
}
|
||||||
pkt_length = (length+IO_SIZE-1) & ~(IO_SIZE-1);
|
pkt_length = (length+IO_SIZE-1) & ~(IO_SIZE-1);
|
||||||
@ -156,10 +181,9 @@ static my_bool net_realloc(NET *net, ulong length)
|
|||||||
NET_HEADER_SIZE + COMP_HEADER_SIZE,
|
NET_HEADER_SIZE + COMP_HEADER_SIZE,
|
||||||
MYF(MY_WME))))
|
MYF(MY_WME))))
|
||||||
{
|
{
|
||||||
net->error=1;
|
net->error= 1;
|
||||||
#ifdef MYSQL_SERVER
|
net->report_error= 1;
|
||||||
net->last_errno=ER_OUT_OF_RESOURCES;
|
net->last_errno= ER_OUT_OF_RESOURCES;
|
||||||
#endif
|
|
||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
}
|
}
|
||||||
net->buff=net->write_pos=buff;
|
net->buff=net->write_pos=buff;
|
||||||
@ -193,14 +217,14 @@ void net_clear(NET *net)
|
|||||||
|
|
||||||
/* Flush write_buffer if not empty. */
|
/* Flush write_buffer if not empty. */
|
||||||
|
|
||||||
int net_flush(NET *net)
|
my_bool net_flush(NET *net)
|
||||||
{
|
{
|
||||||
int error=0;
|
my_bool error= 0;
|
||||||
DBUG_ENTER("net_flush");
|
DBUG_ENTER("net_flush");
|
||||||
if (net->buff != net->write_pos)
|
if (net->buff != net->write_pos)
|
||||||
{
|
{
|
||||||
error=net_real_write(net,(char*) net->buff,
|
error=test(net_real_write(net,(char*) net->buff,
|
||||||
(ulong) (net->write_pos - net->buff));
|
(ulong) (net->write_pos - net->buff)));
|
||||||
net->write_pos=net->buff;
|
net->write_pos=net->buff;
|
||||||
}
|
}
|
||||||
/* Sync packet number if using compression */
|
/* Sync packet number if using compression */
|
||||||
@ -223,7 +247,7 @@ int net_flush(NET *net)
|
|||||||
If compression is used the original package is modified!
|
If compression is used the original package is modified!
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
my_bool
|
||||||
my_net_write(NET *net,const char *packet,ulong len)
|
my_net_write(NET *net,const char *packet,ulong len)
|
||||||
{
|
{
|
||||||
uchar buff[NET_HEADER_SIZE];
|
uchar buff[NET_HEADER_SIZE];
|
||||||
@ -250,23 +274,46 @@ my_net_write(NET *net,const char *packet,ulong len)
|
|||||||
buff[3]= (uchar) net->pkt_nr++;
|
buff[3]= (uchar) net->pkt_nr++;
|
||||||
if (net_write_buff(net,(char*) buff,NET_HEADER_SIZE))
|
if (net_write_buff(net,(char*) buff,NET_HEADER_SIZE))
|
||||||
return 1;
|
return 1;
|
||||||
|
#ifndef DEBUG_DATA_PACKETS
|
||||||
DBUG_DUMP("packet_header",(char*) buff,NET_HEADER_SIZE);
|
DBUG_DUMP("packet_header",(char*) buff,NET_HEADER_SIZE);
|
||||||
|
#endif
|
||||||
return test(net_write_buff(net,packet,len));
|
return test(net_write_buff(net,packet,len));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Send a command to the server.
|
Send a command to the server.
|
||||||
As the command is part of the first data packet, we have to do some data
|
|
||||||
juggling to put the command in there, without having to create a new
|
SYNOPSIS
|
||||||
packet.
|
net_write_command()
|
||||||
This function will split big packets into sub-packets if needed.
|
net NET handler
|
||||||
(Each sub packet can only be 2^24 bytes)
|
command Command in MySQL server (enum enum_server_command)
|
||||||
|
header Header to write after command
|
||||||
|
head_len Length of header
|
||||||
|
packet Query or parameter to query
|
||||||
|
len Length of packet
|
||||||
|
|
||||||
|
DESCRIPTION
|
||||||
|
The reason for having both header and packet is so that libmysql
|
||||||
|
can easy add a header to a special command (like prepared statements)
|
||||||
|
without having to re-alloc the string.
|
||||||
|
|
||||||
|
As the command is part of the first data packet, we have to do some data
|
||||||
|
juggling to put the command in there, without having to create a new
|
||||||
|
packet.
|
||||||
|
This function will split big packets into sub-packets if needed.
|
||||||
|
(Each sub packet can only be 2^24 bytes)
|
||||||
|
|
||||||
|
RETURN VALUES
|
||||||
|
0 ok
|
||||||
|
1 error
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
my_bool
|
||||||
net_write_command(NET *net,uchar command,const char *packet,ulong len)
|
net_write_command(NET *net,uchar command,
|
||||||
|
const char *header, ulong head_len,
|
||||||
|
const char *packet, ulong len)
|
||||||
{
|
{
|
||||||
ulong length=len+1; /* 1 extra byte for command */
|
ulong length=len+1+head_len; /* 1 extra byte for command */
|
||||||
uchar buff[NET_HEADER_SIZE+1];
|
uchar buff[NET_HEADER_SIZE+1];
|
||||||
uint header_size=NET_HEADER_SIZE+1;
|
uint header_size=NET_HEADER_SIZE+1;
|
||||||
DBUG_ENTER("net_write_command");
|
DBUG_ENTER("net_write_command");
|
||||||
@ -277,25 +324,28 @@ net_write_command(NET *net,uchar command,const char *packet,ulong len)
|
|||||||
if (length >= MAX_PACKET_LENGTH)
|
if (length >= MAX_PACKET_LENGTH)
|
||||||
{
|
{
|
||||||
/* Take into account that we have the command in the first header */
|
/* Take into account that we have the command in the first header */
|
||||||
len= MAX_PACKET_LENGTH -1;
|
len= MAX_PACKET_LENGTH - 1 - head_len;
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
int3store(buff, MAX_PACKET_LENGTH);
|
int3store(buff, MAX_PACKET_LENGTH);
|
||||||
buff[3]= (uchar) net->pkt_nr++;
|
buff[3]= (uchar) net->pkt_nr++;
|
||||||
if (net_write_buff(net,(char*) buff, header_size) ||
|
if (net_write_buff(net,(char*) buff, header_size) ||
|
||||||
net_write_buff(net,packet,len))
|
net_write_buff(net, header, head_len) ||
|
||||||
|
net_write_buff(net, packet, len))
|
||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
packet+= len;
|
packet+= len;
|
||||||
length-= MAX_PACKET_LENGTH;
|
length-= MAX_PACKET_LENGTH;
|
||||||
len= MAX_PACKET_LENGTH;
|
len= MAX_PACKET_LENGTH;
|
||||||
|
head_len= 0;
|
||||||
header_size= NET_HEADER_SIZE;
|
header_size= NET_HEADER_SIZE;
|
||||||
} while (length >= MAX_PACKET_LENGTH);
|
} while (length >= MAX_PACKET_LENGTH);
|
||||||
len=length; /* Data left to be written */
|
len=length; /* Data left to be written */
|
||||||
}
|
}
|
||||||
int3store(buff,length);
|
int3store(buff,length);
|
||||||
buff[3]= (uchar) net->pkt_nr++;
|
buff[3]= (uchar) net->pkt_nr++;
|
||||||
DBUG_RETURN(test(net_write_buff(net,(char*) buff,header_size) ||
|
DBUG_RETURN(test(net_write_buff(net, (char*) buff, header_size) ||
|
||||||
net_write_buff(net,packet,len) || net_flush(net)));
|
(head_len && net_write_buff(net, (char*) header, head_len)) ||
|
||||||
|
net_write_buff(net, packet, len) || net_flush(net)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -336,6 +386,9 @@ net_write_buff(NET *net,const char *packet,ulong len)
|
|||||||
else
|
else
|
||||||
left_length= (ulong) (net->buff_end - net->write_pos);
|
left_length= (ulong) (net->buff_end - net->write_pos);
|
||||||
|
|
||||||
|
#ifdef DEBUG_DATA_PACKETS
|
||||||
|
DBUG_DUMP("data", packet, len);
|
||||||
|
#endif
|
||||||
if (len > left_length)
|
if (len > left_length)
|
||||||
{
|
{
|
||||||
if (net->write_pos != net->buff)
|
if (net->write_pos != net->buff)
|
||||||
@ -411,10 +464,12 @@ net_real_write(NET *net,const char *packet,ulong len)
|
|||||||
COMP_HEADER_SIZE, MYF(MY_WME))))
|
COMP_HEADER_SIZE, MYF(MY_WME))))
|
||||||
{
|
{
|
||||||
#ifdef MYSQL_SERVER
|
#ifdef MYSQL_SERVER
|
||||||
net->last_errno=ER_OUT_OF_RESOURCES;
|
net->last_errno= ER_OUT_OF_RESOURCES;
|
||||||
net->error=2;
|
net->error= 2;
|
||||||
|
/* TODO is it needed to set this variable if we have no socket */
|
||||||
|
net->report_error= 1;
|
||||||
#endif
|
#endif
|
||||||
net->reading_or_writing=0;
|
net->reading_or_writing= 0;
|
||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
}
|
}
|
||||||
memcpy(b+header_length,packet,len);
|
memcpy(b+header_length,packet,len);
|
||||||
@ -461,9 +516,10 @@ net_real_write(NET *net,const char *packet,ulong len)
|
|||||||
my_progname,vio_errno(net->vio));
|
my_progname,vio_errno(net->vio));
|
||||||
#endif /* EXTRA_DEBUG */
|
#endif /* EXTRA_DEBUG */
|
||||||
#ifdef MYSQL_SERVER
|
#ifdef MYSQL_SERVER
|
||||||
net->last_errno=ER_NET_ERROR_ON_WRITE;
|
net->last_errno= ER_NET_ERROR_ON_WRITE;
|
||||||
#endif
|
#endif
|
||||||
net->error=2; /* Close socket */
|
net->error= 2; /* Close socket */
|
||||||
|
net->report_error= 1;
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
retry_count=0;
|
retry_count=0;
|
||||||
@ -489,7 +545,8 @@ net_real_write(NET *net,const char *packet,ulong len)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
#endif /* defined(THREAD_SAFE_CLIENT) && !defined(MYSQL_SERVER) */
|
#endif /* defined(THREAD_SAFE_CLIENT) && !defined(MYSQL_SERVER) */
|
||||||
net->error=2; /* Close socket */
|
net->error= 2; /* Close socket */
|
||||||
|
net->report_error= 1;
|
||||||
#ifdef MYSQL_SERVER
|
#ifdef MYSQL_SERVER
|
||||||
net->last_errno= (interrupted ? ER_NET_WRITE_INTERRUPTED :
|
net->last_errno= (interrupted ? ER_NET_WRITE_INTERRUPTED :
|
||||||
ER_NET_ERROR_ON_WRITE);
|
ER_NET_ERROR_ON_WRITE);
|
||||||
@ -667,9 +724,10 @@ my_real_read(NET *net, ulong *complen)
|
|||||||
my_progname,vio_errno(net->vio));
|
my_progname,vio_errno(net->vio));
|
||||||
#endif /* EXTRA_DEBUG */
|
#endif /* EXTRA_DEBUG */
|
||||||
len= packet_error;
|
len= packet_error;
|
||||||
net->error=2; /* Close socket */
|
net->error= 2; /* Close socket */
|
||||||
|
net->report_error= 1;
|
||||||
#ifdef MYSQL_SERVER
|
#ifdef MYSQL_SERVER
|
||||||
net->last_errno=ER_NET_FCNTL_ERROR;
|
net->last_errno= ER_NET_FCNTL_ERROR;
|
||||||
#endif
|
#endif
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
@ -698,7 +756,8 @@ my_real_read(NET *net, ulong *complen)
|
|||||||
DBUG_PRINT("error",("Couldn't read packet: remain: %u errno: %d length: %ld",
|
DBUG_PRINT("error",("Couldn't read packet: remain: %u errno: %d length: %ld",
|
||||||
remain, vio_errno(net->vio), length));
|
remain, vio_errno(net->vio), length));
|
||||||
len= packet_error;
|
len= packet_error;
|
||||||
net->error=2; /* Close socket */
|
net->error= 2; /* Close socket */
|
||||||
|
net->report_error= 1;
|
||||||
#ifdef MYSQL_SERVER
|
#ifdef MYSQL_SERVER
|
||||||
net->last_errno= (interrupted ? ER_NET_READ_INTERRUPTED :
|
net->last_errno= (interrupted ? ER_NET_READ_INTERRUPTED :
|
||||||
ER_NET_READ_ERROR);
|
ER_NET_READ_ERROR);
|
||||||
@ -712,6 +771,8 @@ my_real_read(NET *net, ulong *complen)
|
|||||||
if (i == 0)
|
if (i == 0)
|
||||||
{ /* First parts is packet length */
|
{ /* First parts is packet length */
|
||||||
ulong helping;
|
ulong helping;
|
||||||
|
DBUG_DUMP("packet_header",(char*) net->buff+net->where_b,
|
||||||
|
NET_HEADER_SIZE);
|
||||||
if (net->buff[net->where_b + 3] != (uchar) net->pkt_nr)
|
if (net->buff[net->where_b + 3] != (uchar) net->pkt_nr)
|
||||||
{
|
{
|
||||||
if (net->buff[net->where_b] != (uchar) 255)
|
if (net->buff[net->where_b] != (uchar) 255)
|
||||||
@ -720,7 +781,6 @@ my_real_read(NET *net, ulong *complen)
|
|||||||
("Packets out of order (Found: %d, expected %u)",
|
("Packets out of order (Found: %d, expected %u)",
|
||||||
(int) net->buff[net->where_b + 3],
|
(int) net->buff[net->where_b + 3],
|
||||||
net->pkt_nr));
|
net->pkt_nr));
|
||||||
DBUG_DUMP("packet_header",(char*) net->buff+net->where_b, 4);
|
|
||||||
#ifdef EXTRA_DEBUG
|
#ifdef EXTRA_DEBUG
|
||||||
fprintf(stderr,"Packets out of order (Found: %d, expected %d)\n",
|
fprintf(stderr,"Packets out of order (Found: %d, expected %d)\n",
|
||||||
(int) net->buff[net->where_b + 3],
|
(int) net->buff[net->where_b + 3],
|
||||||
@ -728,6 +788,7 @@ my_real_read(NET *net, ulong *complen)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
len= packet_error;
|
len= packet_error;
|
||||||
|
net->report_error= 1;
|
||||||
#ifdef MYSQL_SERVER
|
#ifdef MYSQL_SERVER
|
||||||
net->last_errno=ER_NET_PACKETS_OUT_OF_ORDER;
|
net->last_errno=ER_NET_PACKETS_OUT_OF_ORDER;
|
||||||
#endif
|
#endif
|
||||||
@ -776,6 +837,10 @@ end:
|
|||||||
vio_blocking(net->vio, net_blocking, &old_mode);
|
vio_blocking(net->vio, net_blocking, &old_mode);
|
||||||
}
|
}
|
||||||
net->reading_or_writing=0;
|
net->reading_or_writing=0;
|
||||||
|
#ifdef DEBUG_DATA_PACKETS
|
||||||
|
if (len != packet_error)
|
||||||
|
DBUG_DUMP("data",(char*) net->buff+net->where_b, len);
|
||||||
|
#endif
|
||||||
return(len);
|
return(len);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -908,7 +973,8 @@ my_net_read(NET *net)
|
|||||||
if (my_uncompress((byte*) net->buff + net->where_b, &packet_len,
|
if (my_uncompress((byte*) net->buff + net->where_b, &packet_len,
|
||||||
&complen))
|
&complen))
|
||||||
{
|
{
|
||||||
net->error=2; /* caller will close socket */
|
net->error= 2; /* caller will close socket */
|
||||||
|
net->report_error= 1;
|
||||||
#ifdef MYSQL_SERVER
|
#ifdef MYSQL_SERVER
|
||||||
net->last_errno=ER_NET_UNCOMPRESS_ERROR;
|
net->last_errno=ER_NET_UNCOMPRESS_ERROR;
|
||||||
#endif
|
#endif
|
||||||
@ -929,12 +995,3 @@ my_net_read(NET *net)
|
|||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool net_request_file(NET* net, const char* fname)
|
|
||||||
{
|
|
||||||
char tmp [FN_REFLEN+1],*end;
|
|
||||||
DBUG_ENTER("net_request_file");
|
|
||||||
tmp[0] = (char) 251; /* NULL_LENGTH */
|
|
||||||
end=strnmov(tmp+1,fname,sizeof(tmp)-2);
|
|
||||||
DBUG_RETURN(my_net_write(net,tmp,(uint) (end-tmp)) ||
|
|
||||||
net_flush(net));
|
|
||||||
}
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user