Commit 3efe8a84 authored by unknown's avatar unknown

Manual merge.

parent c8399bb6
...@@ -14,6 +14,13 @@ ...@@ -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 @@ ...@@ -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 @@ ...@@ -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,...); ...@@ -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); ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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 @@ my_real_read(NET *net, ulong *complen) ...@@ -776,6 +837,10 @@ my_real_read(NET *net, ulong *complen)
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) ...@@ -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) ...@@ -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));
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment