connection.c

来自「postgresql-odbc,跨平台应用」· C语言 代码 · 共 2,634 行 · 第 1/5 页

C
2,634
字号
		SOCK_get_string(sock, msgbuffer, sizeof(msgbuffer));		strncpy(conn->pg_version, msgbuffer, sizeof(conn->pg_version));		strcpy(szVersion, "0.0");		if (sscanf(conn->pg_version, "%d.%d", &major, &minor) >= 2)		{			snprintf(szVersion, sizeof(szVersion), "%d.%d", major, minor);			conn->pg_version_major = major;			conn->pg_version_minor = minor;		}		conn->pg_version_number = (float) atof(szVersion);		if (PG_VERSION_GE(conn, 7.3))			conn->schema_support = 1;		mylog("Got the PostgreSQL version string: '%s'\n", conn->pg_version);		mylog("Extracted PostgreSQL version number: '%1.1f'\n", conn->pg_version_number);		qlog("    [ PostgreSQL version string = '%s' ]\n", conn->pg_version);		qlog("    [ PostgreSQL version number = '%1.1f' ]\n", conn->pg_version_number);	}	else		SOCK_get_string(sock, msgbuffer, sizeof(msgbuffer));inolog("parameter value=%s\n", msgbuffer);}static int	protocol3_opts_array(ConnectionClass *self, const char *opts[][2], BOOL libpqopt, int dim_opts){	ConnInfo	*ci = &(self->connInfo);	const	char	*enc = NULL;	int	cnt;	cnt = 0;	if (libpqopt && ci->server[0])	{		opts[cnt][0] = "host";		opts[cnt++][1] = ci->server;	}	if (libpqopt && ci->port[0])	{		opts[cnt][0] = "port";		opts[cnt++][1] = ci->port;	}	if (ci->database[0])	{		if (libpqopt)		{			opts[cnt][0] = "dbname";	opts[cnt++][1] = ci->database;		}		else		{			opts[cnt][0] = "database";	opts[cnt++][1] = ci->database;		}	}	if (ci->username[0])	{		opts[cnt][0] = "user";		opts[cnt++][1] = ci->username;	}	if (libpqopt)	{		if (ci->sslmode[0])		{			opts[cnt][0] = "sslmode";	opts[cnt++][1] = ci->sslmode;		}		if (ci->password[0])		{			opts[cnt][0] = "password";	opts[cnt++][1] = ci->password;		}	}	else	{		/* DateStyle */		opts[cnt][0] = "DateStyle"; opts[cnt++][1] = "ISO";		/* extra_float_digits */		opts[cnt][0] = "extra_float_digits";	opts[cnt++][1] = "2";		/* geqo */		opts[cnt][0] = "geqo";		if (ci->drivers.disable_optimizer)			opts[cnt++][1] = "off";		else			opts[cnt++][1] = "on";		/* client_encoding */		enc = get_environment_encoding(self, self->original_client_encoding, NULL, TRUE);		if (enc)		{			mylog("startup client_encoding=%s\n", enc);			opts[cnt][0] = "client_encoding"; opts[cnt++][1] = enc;		}	}	return cnt;}static int	protocol3_packet_build(ConnectionClass *self){	CSTR	func = "protocol3_packet_build";	SocketClass	*sock = self->sock;	size_t	slen;	char	*packet, *ppacket;	ProtocolVersion	pversion;	const	char	*opts[20][2];	int	cnt, i;	cnt = protocol3_opts_array(self, opts, FALSE, sizeof(opts) / sizeof(opts[0]));	slen =  sizeof(ProtocolVersion);	for (i = 0; i < cnt; i++)	{		slen += (strlen(opts[i][0]) + 1);		slen += (strlen(opts[i][1]) + 1);	}	slen++;					if (packet = malloc(slen), !packet)	{		CC_set_error(self, CONNECTION_SERVER_NOT_REACHED, "Could not allocate a startup packet", func);		return 0;	}	mylog("sizeof startup packet = %d\n", slen);	sock->pversion = PG_PROTOCOL_LATEST;	/* Send length of Authentication Block */	SOCK_put_int(sock, (Int4) (slen + 4), 4);	ppacket = packet;	pversion = (ProtocolVersion) htonl(sock->pversion);	memcpy(ppacket, &pversion, sizeof(pversion));	ppacket += sizeof(pversion);	for (i = 0; i < cnt; i++)	{ 		strcpy(ppacket, opts[i][0]);		ppacket += (strlen(opts[i][0]) + 1);		strcpy(ppacket, opts[i][1]);		ppacket += (strlen(opts[i][1]) + 1);	}	*ppacket = '\0';	SOCK_put_n_char(sock, packet, (Int4) slen);	SOCK_flush_output(sock);	free(packet);	return 1;}CSTR	l_login_timeout = "connect_timeout";static char	*protocol3_opts_build(ConnectionClass *self){	CSTR	func = "protocol3_opts_build";	size_t	slen;	char	*conninfo, *ppacket;	const	char	*opts[20][2];	int	cnt, i;	BOOL	blankExist;	cnt = protocol3_opts_array(self, opts, TRUE, sizeof(opts) / sizeof(opts[0]));	slen =  sizeof(ProtocolVersion);	for (i = 0, slen = 0; i < cnt; i++)	{		slen += (strlen(opts[i][0]) + 2 + 2); /* add 2 bytes for safety (literal quotes) */		slen += strlen(opts[i][1]);	}	if (self->login_timeout > 0)	{		char	tmout[16];		slen += (strlen(l_login_timeout) + 2 + 2);		snprintf(tmout, sizeof(tmout), FORMAT_UINTEGER, self->login_timeout);		slen += strlen(tmout);	}	slen++;					if (conninfo = malloc(slen), !conninfo)	{		CC_set_error(self, CONNECTION_SERVER_NOT_REACHED, "Could not allocate a connectdb option", func);		return 0;	}	mylog("sizeof connectdb option = %d\n", slen);	for (i = 0, ppacket = conninfo; i < cnt; i++)	{ 		sprintf(ppacket, " %s=", opts[i][0]);		ppacket += (strlen(opts[i][0]) + 2);		blankExist = FALSE;		if (strchr(opts[i][1], ' '))			blankExist = TRUE;		if (blankExist)		{			*ppacket = '\'';			ppacket++;		}		strcpy(ppacket, opts[i][1]);		ppacket += strlen(opts[i][1]);		if (blankExist)		{			*ppacket = '\'';			ppacket++;		}	}	if (self->login_timeout > 0)	{		sprintf(ppacket, " %s=", l_login_timeout);		ppacket += (strlen(l_login_timeout) + 2);		sprintf(ppacket, FORMAT_UINTEGER, self->login_timeout);		ppacket = strchr(ppacket, '\0');	}	*ppacket = '\0';inolog("return conninfo=%s(%d)\n", conninfo, strlen(conninfo));	return conninfo;}static char CC_initial_log(ConnectionClass *self, const char *func){	const ConnInfo	*ci = &self->connInfo;	char	*encoding, vermsg[128];	snprintf(vermsg, sizeof(vermsg), "Driver Version='%s,%s'"#ifdef	WIN32		" linking %d"#ifdef	_MT#ifdef	_DLL		" dynamic"#else		" static"#endif /* _DLL */		" Multithread"#else		" Singlethread"#endif /* _MT */#ifdef	_DEBUG		" Debug"#endif /* DEBUG */		" library"#endif /* WIN32 */		"\n", POSTGRESDRIVERVERSION, PG_BUILD_VERSION#ifdef	_MSC_VER		, _MSC_VER#endif /* _MSC_VER */		);	qlog(vermsg);	mylog(vermsg);	qlog("Global Options: fetch=%d, socket=%d, unknown_sizes=%d, max_varchar_size=%d, max_longvarchar_size=%d\n",		 ci->drivers.fetch_max,		 ci->drivers.socket_buffersize,		 ci->drivers.unknown_sizes,		 ci->drivers.max_varchar_size,		 ci->drivers.max_longvarchar_size);	qlog("                disable_optimizer=%d, ksqo=%d, unique_index=%d, use_declarefetch=%d\n",		 ci->drivers.disable_optimizer,		 ci->drivers.ksqo,		 ci->drivers.unique_index,		 ci->drivers.use_declarefetch);	qlog("                text_as_longvarchar=%d, unknowns_as_longvarchar=%d, bools_as_char=%d NAMEDATALEN=%d\n",		 ci->drivers.text_as_longvarchar,		 ci->drivers.unknowns_as_longvarchar,		 ci->drivers.bools_as_char,		 TABLE_NAME_STORAGE_LEN);	encoding = check_client_encoding(ci->conn_settings);	if (encoding)		self->original_client_encoding = encoding;	else	{		encoding = check_client_encoding(ci->drivers.conn_settings);		if (encoding)			self->original_client_encoding = encoding;	}	if (self->original_client_encoding)		self->ccsc = pg_CS_code(self->original_client_encoding);	qlog("                extra_systable_prefixes='%s', conn_settings='%s' conn_encoding='%s'\n",		 ci->drivers.extra_systable_prefixes,		 ci->drivers.conn_settings,		 encoding ? encoding : "");	if (self->status != CONN_NOT_CONNECTED)	{		CC_set_error(self, CONN_OPENDB_ERROR, "Already connected.", func);		return 0;	}	mylog("%s: DSN = '%s', server = '%s', port = '%s', database = '%s', username = '%s', password='%s'\n", func, ci->dsn, ci->server, ci->port, ci->database, ci->username, ci->password ? "xxxxx" : "");	if (ci->port[0] == '\0' ||#ifdef	WIN32	    ci->server[0] == '\0' ||#endif /* WIN32 */	    ci->database[0] == '\0')	{		CC_set_error(self, CONN_INIREAD_ERROR, "Missing server name, port, or database name in call to CC_connect.", func);		return 0;	}	return 1;}static	char	CC_setenv(ConnectionClass *self);static int LIBPQ_connect(ConnectionClass *self);static charLIBPQ_CC_connect(ConnectionClass *self, char password_req, char *salt_para){	int		ret;	CSTR		func = "LIBPQ_CC_connect";	mylog("%s: entering...\n", func);	if (password_req == AUTH_REQ_OK) /* not yet connected */	{		if (0 == CC_initial_log(self, func))			return 0;	}	if (ret = LIBPQ_connect(self), ret <= 0)		return ret;	CC_setenv(self);	return 1;}static charoriginal_CC_connect(ConnectionClass *self, char password_req, char *salt_para){	StartupPacket sp;	StartupPacket6_2 sp62;	QResultClass *res;	SocketClass *sock;	ConnInfo   *ci = &(self->connInfo);	int			areq = -1;	int			beresp, sockerr;	char		msgbuffer[ERROR_MSG_LENGTH];	char		salt[5], notice[512];	CSTR		func = "original_CC_connect";	// char	   *encoding;	BOOL	startPacketReceived = FALSE;	mylog("%s: entering...\n", func);	if (password_req != AUTH_REQ_OK)	{		sock = self->sock;		/* already connected, just authenticate */		CC_clear_error(self);		}	else	{		if (0 == CC_initial_log(self, func))			return 0;another_version_retry:		/*		 * If the socket was closed for some reason (like a SQLDisconnect,		 * but no SQLFreeConnect then create a socket now.		 */		if (!self->sock)		{			self->sock = SOCK_Constructor(self);			if (!self->sock)			{				CC_set_error(self, CONNECTION_SERVER_NOT_REACHED, "Could not construct a socket to the server", func);				return 0;			}		}		sock = self->sock;		mylog("connecting to the server socket...\n");		SOCK_connect_to(sock, (short) atoi(ci->port), ci->server, self->login_timeout);		if (SOCK_get_errcode(sock) != 0)		{			CC_set_error(self, CONNECTION_SERVER_NOT_REACHED, "Could not connect to the server", func);			return 0;		}		mylog("connection to the server socket succeeded.\n");inolog("protocol=%s version=%d,%d\n", ci->protocol, self->pg_version_major, self->pg_version_minor);		if (PROTOCOL_62(ci))		{			sock->reverse = TRUE;		/* make put_int and get_int work										 * for 6.2 */			memset(&sp62, 0, sizeof(StartupPacket6_2));			sock->pversion = PG_PROTOCOL_62;			SOCK_put_int(sock, htonl(4 + sizeof(StartupPacket6_2)), 4);			sp62.authtype = htonl(NO_AUTHENTICATION);			strncpy(sp62.database, ci->database, PATH_SIZE);			strncpy(sp62.user, ci->username, USRNAMEDATALEN);			SOCK_put_n_char(sock, (char *) &sp62, sizeof(StartupPacket6_2));			SOCK_flush_output(sock);		}		else if (PROTOCOL_74(ci))		{			if (!protocol3_packet_build(self))				return 0;		}		else		{			memset(&sp, 0, sizeof(StartupPacket));			mylog("sizeof startup packet = %d\n", sizeof(StartupPacket));			if (PROTOCOL_63(ci))				sock->pversion = PG_PROTOCOL_63;			else				sock->pversion = PG_PROTOCOL_64;			/* Send length of Authentication Block */			SOCK_put_int(sock, 4 + sizeof(StartupPacket), 4);			sp.protoVersion = (ProtocolVersion) htonl(sock->pversion);			strncpy(sp.database, ci->database, SM_DATABASE);			strncpy(sp.user, ci->username, SM_USER);			SOCK_put_n_char(sock, (char *) &sp, sizeof(StartupPacket));			SOCK_flush_output(sock);		}		if (SOCK_get_errcode(sock) != 0)		{			CC_set_error(self, CONN_INVALID_AUTHENTICATION, "Failed to send the authentication packet", func);			return 0;		}		mylog("sent the authentication block successfully.\n");	}	mylog("gonna do authentication\n");	/*	 * Now get the authentication request from backend	 */	if (!PROTOCOL_62(ci))	{		BOOL		beforeV2 = PG_VERSION_LT(self, 6.4),					ReadyForQuery = FALSE, retry = FALSE;		uint32	leng;		do		{			if (password_req != AUTH_REQ_OK)			{				beresp = 'R';				startPacketReceived = TRUE;			}			else			{				beresp = SOCK_get_id(sock);				mylog("auth got '%c'\n", beresp);				if (0 != SOCK_get_errcode(sock))					goto sockerr_proc;				if (PROTOCOL_74(ci))				{					if (beresp != 'E' || startPacketReceived)					{						leng = SOCK_get_response_length(sock);inolog("leng=%d\n", leng);						if (0 != SOCK_get_errcode(sock))							goto sockerr_proc;					}					else						strncpy(ci->protocol, PG74REJECTED, sizeof(ci->protocol));/* retry = TRUE; */				}				startPacketReceived = TRUE;			}			switch (beresp)			{				case 'E':inolog("Ekita\n");					handle_error_message(self, msgbuffer, sizeof(msgbuffer), self->sqlstate, func, NULL);					CC_set_error(self, CONN_INVALID_AUTHENTICATION, msgbuffer, func);					qlog("ERROR from backend during authentication: '%s'\n", msgbuffer);					if (strnicmp(msgbuffer, "Unsupported frontend protocol", 29) == 0)						retry = TRUE;					else if (strncmp(msgbuffer, "FATAL:", 6) == 0 &&						 strnicmp(msgbuffer + 8, "unsupported frontend protocol", 29) == 0)						retry = TRUE;					if (retry)						break;					return 0;				case 'R':					if (password_req != AUTH_REQ_OK)					{						mylog("in 'R' password_req=%s\n", ci->password);						areq = password_req;						if (salt_para)							memcpy(salt, salt_para, sizeof(salt));						password_req = AUTH_REQ_OK;						mylog("salt=%02x%02x%02x%02x%02x\n", (UCHAR)salt[0], (UCHAR)salt[1], (UCHAR)salt[2], (UCHAR)salt[3], (UCHAR)salt[4]);					}					else					{						areq = SOCK_get_int(sock, 4);						memset(salt, 0, sizeof(salt));						if (areq == AUTH_REQ_MD5)							SOCK_get_n_char(sock, salt, 4);						else if (areq == AUTH_REQ_CRYPT)							SOCK_get_n_char(sock, salt, 2);						mylog("areq = %d salt=%02x%02x%02x%02x%02x\n", areq, (UCHAR)salt[0], (UCHAR)salt[1], (UCHAR)salt[2], (UCHAR)salt[3], (UCHAR)salt[4]);					}					switch (areq)					{						case AUTH_REQ_OK:							break;						case AUTH_REQ_KRB4:							CC_set_error(self, CONN_AUTH_TYPE_UNSUPPORTED, "Kerberos 4 authentication not supported", func);							return 0;						case AUTH_REQ_KRB5:							CC_set_error(self, CONN_AUTH_TYPE_UNSUPPORTED, "Kerberos 5 authentication not supported", func);							return 0;						case AUTH_REQ_PASSWORD:							mylog("in AUTH_REQ_PASSWORD\n");							if (ci->password[0] == '\0')							{								CC_set_error(self, CONNECTION_NEED_PASSWORD, "A password is required for this connection.", func);								return -areq;		/* need password */							}							mylog("past need password\n");

⌨️ 快捷键说明

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