📄 net.c
字号:
/* Copyright Abandoned 1996 TCX DataKonsult AB & Monty Program KB & Detron HB This file is public domain and comes with NO WARRANTY of any kind *//* Write and read of logical packets to/from socket** Writes are cached into net_buffer_length big packets.** Read packets are reallocated dynamicly when reading big packets.** Each logical packet has the following pre-info:** 3 byte length & 1 byte package-number.*/#ifdef __WIN__#include <winsock.h>#endif#include <global.h>#include <violite.h>#include <my_sys.h>#include <m_string.h>#include "mysql.h"#include "mysqld_error.h"#include <signal.h>#include <errno.h>#include <sys/types.h>#include <violite.h>#ifdef MYSQL_SERVERulong max_allowed_packet=65536;extern ulong net_read_timeout,net_write_timeout;extern uint test_flags;#elseulong max_allowed_packet=16*1024*1024L;ulong net_read_timeout= NET_READ_TIMEOUT;ulong net_write_timeout= NET_WRITE_TIMEOUT;#endifulong net_buffer_length=8192; /* Default length. Enlarged if necessary */#if !defined(__WIN__) && !defined(MSDOS)#include <sys/socket.h>#else#undef MYSQL_SERVER /* Win32 can't handle interrupts */#endif#if !defined(MSDOS) && !defined(__WIN__) && !defined(HAVE_BROKEN_NETINET_INCLUDES) && !defined(__BEOS__)#include <netinet/in_systm.h>#include <netinet/in.h>#include <netinet/ip.h>#if !defined(alpha_linux_port)#include <netinet/tcp.h>#endif#endif#include "mysqld_error.h"#ifdef MYSQL_SERVER#include "my_pthread.h"#include "thr_alarm.h"void sql_print_error(const char *format,...);#define RETRY_COUNT mysqld_net_retry_countextern ulong mysqld_net_retry_count;#else#ifdef OS2 /* avoid name conflict */#define thr_alarm_t thr_alarm_t_net#define ALARM ALARM_net#endiftypedef my_bool thr_alarm_t;typedef my_bool ALARM;#define thr_alarm_init(A) (*(A))=0#define thr_alarm_in_use(A) (*(A)!= 0)#define thr_end_alarm(A)#define thr_alarm(A,B,C) local_thr_alarm((A),(B),(C))inline int local_thr_alarm(my_bool *A,int B __attribute__((unused)),ALARM *C __attribute__((unused))){ *A=1; return 0;}#define thr_got_alarm(A) 0#define RETRY_COUNT 1#endif#ifdef MYSQL_SERVERextern ulong bytes_sent, bytes_received; extern pthread_mutex_t LOCK_bytes_sent , LOCK_bytes_received;#else#undef statistic_add#define statistic_add(A,B,C)#endif/*** Give error if a too big packet is found** The server can change this with the -O switch, but because the client** can't normally do this the client should have a bigger max-buffer.*/#define TEST_BLOCKING 8static int net_write_buff(NET *net,const char *packet,uint len); /* Init with packet info */int my_net_init(NET *net, Vio* vio){ if (!(net->buff=(uchar*) my_malloc(net_buffer_length,MYF(MY_WME)))) return 1; if (net_buffer_length > max_allowed_packet) max_allowed_packet=net_buffer_length; net->buff_end=net->buff+(net->max_packet=net_buffer_length); net->vio = vio; net->no_send_ok = 0; net->error=0; net->return_errno=0; net->return_status=0; net->timeout=(uint) net_read_timeout; /* Timeout for read */ net->pkt_nr=0; net->write_pos=net->read_pos = net->buff; net->last_error[0]=0; net->compress=0; net->reading_or_writing=0; net->where_b = net->remain_in_buf=0; net->last_errno=0; if (vio != 0) /* If real connection */ { net->fd = vio_fd(vio); /* For perl DBI/DBD */#if defined(MYSQL_SERVER) && !defined(___WIN__) && !defined(__EMX__) && !defined(OS2) if (!(test_flags & TEST_BLOCKING)) vio_blocking(vio, FALSE);#endif vio_fastsend(vio); } return 0;}void net_end(NET *net){ my_free((gptr) net->buff,MYF(MY_ALLOW_ZERO_PTR)); net->buff=0;}/* Realloc the packet buffer */static my_bool net_realloc(NET *net, ulong length){ uchar *buff; ulong pkt_length; if (length >= max_allowed_packet) { DBUG_PRINT("error",("Packet too large (%lu)", length)); net->error=1; net->last_errno=ER_NET_PACKET_TOO_LARGE; return 1; } pkt_length = (length+IO_SIZE-1) & ~(IO_SIZE-1); if (!(buff=(uchar*) my_realloc((char*) net->buff, pkt_length, MYF(MY_WME)))) { net->error=1;#ifdef MYSQL_SERVER net->last_errno=ER_OUT_OF_RESOURCES;#endif return 1; } net->buff=net->write_pos=buff; net->buff_end=buff+(net->max_packet=pkt_length); return 0;} /* Remove unwanted characters from connection */void net_clear(NET *net){#ifndef EXTRA_DEBUG int count; bool is_blocking=vio_is_blocking(net->vio); if (is_blocking) vio_blocking(net->vio, FALSE); if (!vio_is_blocking(net->vio)) /* Safety if SSL */ { while ( (count = vio_read(net->vio, (char*) (net->buff), net->max_packet)) > 0) DBUG_PRINT("info",("skipped %d bytes from file: %s", count,vio_description(net->vio))); if (is_blocking) vio_blocking(net->vio, TRUE); }#endif /* EXTRA_DEBUG */ net->pkt_nr=0; /* Ready for new command */ net->write_pos=net->buff;} /* Flush write_buffer if not empty. */int my_net_flush(NET *net){ int error=0; DBUG_ENTER("my_net_flush"); if (net->buff != net->write_pos) { error=net_real_write(net,(char*) net->buff, (uint) (net->write_pos - net->buff)); net->write_pos=net->buff; } DBUG_RETURN(error);}/******************************************************************************* Write something to server/client buffer*****************************************************************************//*** Write a logical packet with packet header** Format: Packet length (3 bytes), packet number(1 byte)** When compression is used a 3 byte compression length is added** NOTE: If compression is used the original package is destroyed!*/intmy_net_write(NET *net,const char *packet,ulong len){ uchar buff[NET_HEADER_SIZE]; int3store(buff,len); buff[3]= (net->compress) ? 0 : (uchar) (net->pkt_nr++); if (net_write_buff(net,(char*) buff,NET_HEADER_SIZE)) return 1; return net_write_buff(net,packet,len);}intnet_write_command(NET *net,uchar command,const char *packet,ulong len){ uchar buff[NET_HEADER_SIZE+1]; uint length=len+1; /* 1 extra byte for command */ int3store(buff,length); buff[3]= (net->compress) ? 0 : (uchar) (net->pkt_nr++); buff[4]=command; if (net_write_buff(net,(char*) buff,5)) return 1; return test(net_write_buff(net,packet,len) || my_net_flush(net));}static intnet_write_buff(NET *net,const char *packet,uint len){ uint left_length=(uint) (net->buff_end - net->write_pos); while (len > left_length) { memcpy((char*) net->write_pos,packet,left_length); if (net_real_write(net,(char*) net->buff,net->max_packet)) return 1; net->write_pos=net->buff; packet+=left_length; len-=left_length; left_length=net->max_packet; } memcpy((char*) net->write_pos,packet,len); net->write_pos+=len; return 0;}/* Read and write using timeouts */intnet_real_write(NET *net,const char *packet,ulong len){ int length; char *pos,*end; thr_alarm_t alarmed;#if !defined(__WIN__) && !defined(__EMX__) && !defined(OS2) ALARM alarm_buff;#endif uint retry_count=0; my_bool net_blocking = vio_is_blocking(net->vio); DBUG_ENTER("net_real_write"); if (net->error == 2) DBUG_RETURN(-1); /* socket can't be used */ net->reading_or_writing=2;#ifdef HAVE_COMPRESS if (net->compress) { ulong complen; uchar *b; uint header_length=NET_HEADER_SIZE+COMP_HEADER_SIZE; if (!(b=(uchar*) my_malloc(len + NET_HEADER_SIZE + COMP_HEADER_SIZE, MYF(MY_WME)))) {#ifdef MYSQL_SERVER net->last_errno=ER_OUT_OF_RESOURCES; net->error=2;#endif net->reading_or_writing=0; DBUG_RETURN(1); } memcpy(b+header_length,packet,len); if (my_compress((byte*) b+header_length,&len,&complen)) { DBUG_PRINT("warning", ("Compression error; Continuing without compression")); complen=0; } int3store(&b[NET_HEADER_SIZE],complen); int3store(b,len); b[3]=(uchar) (net->pkt_nr++); len+= header_length; packet= (char*) b; }#endif /* HAVE_COMPRESS */ /* DBUG_DUMP("net",packet,len); */#ifdef MYSQL_SERVER thr_alarm_init(&alarmed); if (net_blocking) thr_alarm(&alarmed,(uint) net_write_timeout,&alarm_buff);#else alarmed=0;#endif /* MYSQL_SERVER */ pos=(char*) packet; end=pos+len; while (pos != end) { if ((int) (length=vio_write(net->vio,pos,(int) (end-pos))) <= 0) { my_bool interrupted = vio_should_retry(net->vio);#if (!defined(__WIN__) && !defined(__EMX__) && !defined(OS2)) if ((interrupted || length==0) && !thr_alarm_in_use(&alarmed)) { if (!thr_alarm(&alarmed,(uint) net_write_timeout,&alarm_buff)) { /* Always true for client */ if (!vio_is_blocking(net->vio)) { while (vio_blocking(net->vio, TRUE) < 0) { if (vio_should_retry(net->vio) && retry_count++ < RETRY_COUNT) continue;#ifdef EXTRA_DEBUG fprintf(stderr,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -