⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mysqlnd_wireprotocol.c

📁 linux下安装不上mysql5与php5的可用此关联
💻 C
📖 第 1 页 / 共 3 页
字号:
		if (first_iteration && header.size > buf_size) {			first_iteration = FALSE;			/*			  We need a trailing \0 for the last string, in case of text-mode,			  to be able to implement read-only variables.			*/			p = new_buf = emalloc(header.size + 1);			net->stream->chunk_size = header.size;		} else if (!first_iteration) {			/* Empty packet after MYSQLND_MAX_PACKET_SIZE packet. That's ok, break */			if (!header.size) {				break;			}			/*			  We have to realloc the buffer.			  We need a trailing \0 for the last string, in case of text-mode,			  to be able to implement read-only variables.			*/			new_buf = erealloc(new_buf, *data_size + 1);			/* The position could have changed, recalculate */			p = new_buf + (*data_size - header.size);		}		if (!mysqlnd_read_body(conn, p, header.size TSRMLS_CC)) {			php_error(E_WARNING, "Empty row packet body");			ret = FAIL;			break;		}		if (header.size < MYSQLND_MAX_PACKET_SIZE) {			break;		}	}	if (ret == PASS && new_buf) {		*buf = new_buf;	}	return ret;}/* {{{ php_mysqlnd_rowp_read_binary_protocol */staticvoid php_mysqlnd_rowp_read_binary_protocol(php_mysql_packet_row *packet, MYSQLND *conn,										   zend_uchar *p, size_t data_size TSRMLS_DC){	int i;	zend_uchar *null_ptr, bit;	zval **current_field, **end_field, **start_field;	zend_bool as_unicode = conn->options.numeric_and_datetime_as_unicode;	end_field = (current_field = start_field = packet->fields) + packet->field_count;	/* skip the first byte, not 0xFE -> 0x0, status */	p++;	null_ptr= p;	p += (packet->field_count + 9)/8;		/* skip null bits */	bit	= 4;								/* first 2 bits are reserved */	for (i = 0; current_field < end_field; current_field++, i++) {		MAKE_STD_ZVAL(*current_field);		if (*null_ptr & bit) {			ZVAL_NULL(*current_field);		} else {			enum_mysqlnd_field_types type = packet->fields_metadata[i].type;			mysqlnd_ps_fetch_functions[type].func(*current_field, &packet->fields_metadata[i],												  0, &p, as_unicode TSRMLS_CC);		}		if (!((bit<<=1) & 255)) {			bit= 1;					/* To next byte */			null_ptr++;		}	}	/* Normal queries: The buffer has one more byte at the end, because we need it */	packet->row_buffer[data_size] = '\0';}/* }}} *//* {{{ php_mysqlnd_rowp_read_text_protocol */staticvoid php_mysqlnd_rowp_read_text_protocol(php_mysql_packet_row *packet, MYSQLND *conn,										 zend_uchar *p, size_t data_size TSRMLS_DC){	int i;	zend_bool last_field_was_string;	zval **current_field, **end_field, **start_field;	zend_bool as_unicode = conn->options.numeric_and_datetime_as_unicode;#ifdef MYSQLND_STRING_TO_INT_CONVERSION	zend_bool as_int = conn->options.int_and_year_as_int;#endif	end_field = (current_field = start_field = packet->fields) + packet->field_count;	for (i = 0; current_field < end_field; current_field++, i++) {		/* Don't reverse the order. It is significant!*/		void *obj;		zend_bool allocated;		zend_uchar *this_field_len_pos = p;		/* php_mysqlnd_net_field_length() call should be after *this_field_len_pos = p; */		unsigned long len = php_mysqlnd_net_field_length(&p);		obj = mysqlnd_palloc_get_zval(conn->zval_cache, &allocated);		if (allocated) {			*current_field = (zval *) obj;		} else {			/* It's from the cache, so we can upcast here */			*current_field = &((mysqlnd_zval *) obj)->zv;						((mysqlnd_zval *) obj)->copy_alloced_on_result_free = FALSE;		}		if (current_field > start_field && last_field_was_string) {			/*			  Normal queries: 			  We have to put \0 now to the end of the previous field,			  if it was a string. IS_NULL doesn't matter. Because we			  have already read our length, then we can overwrite it			  in the row buffer.			  This statement terminates the previous field, not the current one. 			  NULL_LENGTH is encoded in one byte, so we can stick a \0 there.			  Any string length is encoded in at least one byte, so we can stick			  a \0 there.			*/			*this_field_len_pos = '\0';		}		/* NULL or NOT NULL, this is the question! */		if (len == MYSQLND_NULL_LENGTH) {			ZVAL_NULL(*current_field);			last_field_was_string = FALSE;		} else {			struct st_mysqlnd_perm_bind perm_bind =					mysqlnd_ps_fetch_functions[packet->fields_metadata[i].type];#ifdef MYSQLND_STRING_TO_INT_CONVERSION			if (as_int && perm_bind.php_type == IS_LONG &&				perm_bind.pack_len <= SIZEOF_LONG)			{				zend_uchar save = *(p + len);				/* We have to make it ASCIIZ temporarily */				*(p + len) = '\0';				if (perm_bind.pack_len < SIZEOF_LONG)				{					/* direct conversion */					my_int64 v = atoll((char *) p);					ZVAL_LONG(*current_field, v);				} else {					my_uint64 v = (my_uint64) atoll((char *) p);					zend_bool uns = packet->fields_metadata[i].flags & UNSIGNED_FLAG? TRUE:FALSE;					/* We have to make it ASCIIZ temporarily */#if SIZEOF_LONG==8  					if (uns == TRUE && v > 9223372036854775807L)#elif SIZEOF_LONG==4					if ((uns == TRUE && v > L64(2147483647)) || 					    (uns == FALSE && (( L64(2147483647) < (my_int64) v) ||						(L64(-2147483648) > (my_int64) v))))#endif					{						ZVAL_STRINGL(*current_field, (char *)p, len, 0);					} else {						ZVAL_LONG(*current_field, (my_int64)v);										}				}				*(p + len) = save;			} else#endif#if PHP_MAJOR_VERSION < 6			{				ZVAL_STRINGL(*current_field, (char *)p, len, 0);			}#else			/*			  Here we have to convert to UTF16, which means not reusing the buffer.			  Which in turn means that we can free the buffers once we have			  stored the result set, if we use store_result(). Also the destruction			  of the zvals should not call zval_copy_ctor() because then we will leak.			  I suppose we can use UG(unicode) in mysqlnd.c/mysqlnd_palloc.c when			  freeing a result set			  to check if we need to call copy_ctor().			  XXX: Keep in mind that up there there is an open `else` in			       #ifdef MYSQLND_STRING_TO_INT_CONVERSION			*/			if ((perm_bind.is_possibly_blob == TRUE &&				packet->fields_metadata[i].charsetnr == MYSQLND_BINARY_CHARSET_NR) ||				(!as_unicode && perm_bind.can_ret_as_str_in_uni == TRUE))			{				/* BLOB - no conversion please */				ZVAL_STRINGL(*current_field,  (char *)p, len, UG(unicode));			} else {				ZVAL_UTF8_STRINGL(*current_field,  (char *)p, len, 0);			}#endif			p += len;			last_field_was_string = TRUE;		}	}	if (last_field_was_string) {		/* Normal queries: The buffer has one more byte at the end, because we need it */		packet->row_buffer[data_size] = '\0';	}}/* }}} *//* {{{ php_mysqlnd_rowp_read *//*  if normal statements => packet->fields is created by this function,   if PS => packet->fields is passed from outside*/static enum_func_statusphp_mysqlnd_rowp_read(void *_packet, MYSQLND *conn TSRMLS_DC){	MYSQLND_NET *net = &conn->net;	zend_uchar *p;	enum_func_status ret = PASS;	size_t data_size = 0;	size_t old_chunk_size = net->stream->chunk_size;	php_mysql_packet_row *packet= (php_mysql_packet_row *) _packet;	if (FAIL == (ret = php_mysqlnd_read_row_ex(conn, &packet->row_buffer, 0, &data_size TSRMLS_CC))) {		goto end;	}	/* packet->row_buffer is of size 'data_size + 1' */	packet->header.size = data_size;	if ((*(p = packet->row_buffer)) == 0xFE && data_size < 8) { /* EOF */		packet->eof = TRUE;		p++;		if (data_size > 1) {			packet->warning_count = uint2korr(p);			p += 2;			packet->server_status = uint2korr(p);			/* Seems we have 3 bytes reserved for future use */		}		goto end;	} else {		MYSQLND_INC_CONN_STATISTIC(&conn->stats, STAT_ROWS_FETCHED_FROM_SERVER);		packet->eof = FALSE;		/* packet->field_count is set by the user of the packet */		if (!packet->skip_extraction) {			if (!packet->fields) {				/*				  old-API will probably set packet->fields to NULL every time, though for				  unbuffered sets it makes not much sense as the zvals in this buffer matter,				  not the buffer. Constantly allocating and deallocating brings nothing.				  For PS - if stmt_store() is performed, thus we don't have a cursor, it will				  behave just like old-API buffered. Cursors will behave like a bit different,				  but mostly like old-API unbuffered and thus will populate this array with				  value.				*/				packet->fields = (zval **) emalloc(packet->field_count * sizeof(zval *));			}			if (packet->binary_protocol) {				php_mysqlnd_rowp_read_binary_protocol(packet, conn, p, data_size TSRMLS_CC);			} else {				php_mysqlnd_rowp_read_text_protocol(packet, conn, p, data_size TSRMLS_CC);			}		} else {			MYSQLND_INC_CONN_STATISTIC(&conn->stats, STAT_ROWS_SKIPPED);		}	}end:	net->stream->chunk_size = old_chunk_size;	return ret;}/* }}} *//* {{{ php_mysqlnd_rowp_free_mem */staticvoid php_mysqlnd_rowp_free_mem(void *_packet, zend_bool alloca){	php_mysql_packet_row *p= (php_mysql_packet_row *) _packet;	if (p->row_buffer) {		efree(p->row_buffer);		p->row_buffer = NULL;	}	/*	  Don't free packet->fields :	  - normal queries -> store_result() | fetch_row_unbuffered() will transfer	    the ownership and NULL it.	  - PS will pass in it the bound variables, we have to use them! and of course	    not free the array. As it is passed to us, we should not clean it ourselves.	*/	if (!alloca) {		efree(p);	}}/* }}} *//* {{{ php_mysqlnd_stats_read */static enum_func_statusphp_mysqlnd_stats_read(void *_packet, MYSQLND *conn TSRMLS_DC){	zend_uchar buf[1024];	php_mysql_packet_stats *packet= (php_mysql_packet_stats *) _packet;	PACKET_READ_HEADER_AND_BODY(packet, conn, buf, sizeof(buf), "statistics");	packet->message = emalloc(packet->header.size + 1);	memcpy(packet->message, buf, packet->header.size);	packet->message[packet->header.size] = '\0';	packet->message_len = packet->header.size;	return PASS;}/* }}} *//* {{{ php_mysqlnd_stats_free_mem */staticvoid php_mysqlnd_stats_free_mem(void *_packet, zend_bool alloca){	php_mysql_packet_stats *p= (php_mysql_packet_stats *) _packet;	if (p->message) {		efree(p->message);		p->message = NULL;	}	if (!alloca) {		efree(p);	}}/* }}} *//* 1 + 4 (id) + 2 (field_c) + 2 (param_c) + 1 (filler) + 2 (warnings ) */#define PREPARE_RESPONSE_SIZE_41 9#define PREPARE_RESPONSE_SIZE_50 12/* {{{ php_mysqlnd_prepare_read */static enum_func_statusphp_mysqlnd_prepare_read(void *_packet, MYSQLND *conn TSRMLS_DC){	/* In case of an error, we should have place to put it */	zend_uchar buf[1024];	zend_uchar *p= buf;	unsigned int data_size;	php_mysql_packet_prepare_response *packet= (php_mysql_packet_prepare_response *) _packet;	PACKET_READ_HEADER_AND_BODY(packet, conn, buf, sizeof(buf), "prepare");		data_size = packet->header.size;	packet->error_code = uint1korr(p);	p++;	if (0xFF == packet->error_code) {		php_mysqlnd_read_error_from_line(p, data_size - 1,										 packet->error_info.error, sizeof(packet->error_info.error),										 &packet->error_info.error_no,										 packet->error_info.sqlstate);		return PASS;	}	if (data_size != PREPARE_RESPONSE_SIZE_41 &&		data_size != PREPARE_RESPONSE_SIZE_50 &&		!(data_size > PREPARE_RESPONSE_SIZE_50)) {		php_error(E_WARNING, "Wrong COM_STMT_PREPARE response size. Received %d", data_size);		return FAIL;	}	packet->stmt_id = uint4korr(p);	p += 4;	/* Number of columns in result set */	packet->field_count = uint2korr(p);	p += 2;	packet->param_count = uint2korr(p);	p += 2;	/* 0x0 filler sent by the server for 4.1 clients */	p++;	if (data_size >= 12) {		packet->warning_count= uint2korr(p);	}#ifndef MYSQLND_SILENT	php_printf("\tPrepare packet read: stmt_id=%d fields=%d params=%d\n",				packet->stmt_id, packet->field_count, packet->param_count);#endif	return PASS;}/* }}} *//* {{{ php_mysqlnd_prepare_free_mem */staticvoid php_mysqlnd_prepare_free_mem(void *_packet, zend_bool alloca){	php_mysql_packet_prepare_response *p= (php_mysql_packet_prepare_response *) _packet;	if (!alloca) {		efree(p);	}}/* }}} *//* {{{ php_mysqlnd_chg_user_read */static enum_func_statusphp_mysqlnd_chg_user_read(void *_packet, MYSQLND *conn TSRMLS_DC){	/* There could be an error message */	zend_uchar buf[1024];	zend_uchar *p= buf;	php_mysql_packet_chg_user_resp *packet= (php_mysql_packet_chg_user_resp *) _packet;	PACKET_READ_HEADER_AND_BODY(packet, conn, buf, sizeof(buf), "change user response ");	/*	  Don't increment. First byte is 0xFF on error, but otherwise is starting byte	  of encoded sequence for length.	*/	/* Should be always 0x0 or 0xFF for error */	packet->field_count= uint1korr(p);	p++;	if (packet->header.size == 1 && buf[0] == 0xFE &&		packet->server_capabilities & CLIENT_SECURE_CONNECTION) {		/* We don't handle 3.23 authentication */		return FAIL;	}	if (0xFF == packet->field_count) {		php_mysqlnd_read_error_from_line(p, packet->header.size - 1,										 packet->error_info.error,										 sizeof(packet->error_info.error),										 &packet->error_info.error_no,										 packet->error_info.sqlstate);	}	return PASS;}/* }}} *//* {{{ php_mysqlnd_chg_user_free_mem */staticvoid php_mysqlnd_chg_user_free_mem(void *_packet, zend_bool alloca){	if (!alloca) {		efree(_packet);	}}/* }}} *//* {{{ packet_methods  */mysqlnd_packet_methods packet_methods[PROT_LAST] ={	{		sizeof(php_mysql_packet_greet),		php_mysqlnd_greet_read,		NULL, /* write */		php_mysqlnd_greet_free_mem,	}, /* PROT_GREET_PACKET */	{		sizeof(php_mysql_packet_auth),		NULL, /* read */		php_mysqlnd_auth_write,		php_mysqlnd_auth_free_mem,	}, /* PROT_AUTH_PACKET */	{		sizeof(php_mysql_packet_ok),		php_mysqlnd_ok_read, /* read */		NULL, /* write */		php_mysqlnd_ok_free_mem,	}, /* PROT_OK_PACKET */	{		sizeof(php_mysql_packet_eof),		php_mysqlnd_eof_read, /* read */		NULL, /* write */		php_mysqlnd_eof_free_mem,	}, /* PROT_EOF_PACKET */	{		sizeof(php_mysql_packet_command),		NULL, /* read */		php_mysqlnd_cmd_write, /* write */		php_mysqlnd_cmd_free_mem,	}, /* PROT_CMD_PACKET */	{		sizeof(php_mysql_packet_rset_header),		php_mysqlnd_rset_header_read, /* read */		NULL, /* write */		php_mysqlnd_rset_header_free_mem,	}, /* PROT_RSET_HEADER_PACKET */	{		sizeof(php_mysql_packet_res_field),		php_mysqlnd_rset_field_read, /* read */		NULL, /* write */		php_mysqlnd_rset_field_free_mem,	}, /* PROT_RSET_FLD_PACKET */	{		sizeof(php_mysql_packet_row),		php_mysqlnd_rowp_read, /* read */		NULL, /* write */		php_mysqlnd_rowp_free_mem,	}, /* PROT_ROW_PACKET */	{		sizeof(php_mysql_packet_stats),		php_mysqlnd_stats_read, /* read */		NULL, /* write */		php_mysqlnd_stats_free_mem,	}, /* PROT_STATS_PACKET */	{		sizeof(php_mysql_packet_prepare_response),		php_mysqlnd_prepare_read, /* read */		NULL, /* write */		php_mysqlnd_prepare_free_mem,	}, /* PROT_PREPARE_RESP_PACKET */	{		sizeof(php_mysql_packet_chg_user_resp),		php_mysqlnd_chg_user_read, /* read */		NULL, /* write */		php_mysqlnd_chg_user_free_mem,	} /* PROT_CHG_USER_PACKET */};/* }}} *//* * Local variables: * tab-width: 4 * c-basic-offset: 4 * End: * vim600: noet sw=4 ts=4 fdm=marker * vim<600: noet sw=4 ts=4 */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -