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

📄 fe-connect.c

📁 PostgreSQL 8.1.4的源码 适用于Linux下的开源数据库系统
💻 C
📖 第 1 页 / 共 5 页
字号:
						goto keep_going;					}					/*					 * if sslmode is "prefer" and we're in an SSL connection,					 * then do a non-SSL retry					 */					if (conn->sslmode[0] == 'p' /* "prefer" */						&& conn->ssl						&& conn->allow_ssl_try	/* redundant? */						&& !conn->wait_ssl_try) /* redundant? */					{						/* only retry once */						conn->allow_ssl_try = false;						/* Must drop the old connection */						pqsecure_close(conn);						closesocket(conn->sock);						conn->sock = -1;						conn->status = CONNECTION_NEEDED;						goto keep_going;					}#endif					goto error_return;				}				/* It is an authentication request. */				/* Get the type of request. */				if (pqGetInt((int *) &areq, 4, conn))				{					/* We'll come back when there are more data */					return PGRES_POLLING_READING;				}				/* Get the password salt if there is one. */				if (areq == AUTH_REQ_MD5)				{					if (pqGetnchar(conn->md5Salt,								   sizeof(conn->md5Salt), conn))					{						/* We'll come back when there are more data */						return PGRES_POLLING_READING;					}				}				if (areq == AUTH_REQ_CRYPT)				{					if (pqGetnchar(conn->cryptSalt,								   sizeof(conn->cryptSalt), conn))					{						/* We'll come back when there are more data */						return PGRES_POLLING_READING;					}				}				/*				 * OK, we successfully read the message; mark data consumed				 */				conn->inStart = conn->inCursor;				/* Respond to the request if necessary. */				/*				 * Note that conn->pghost must be non-NULL if we are going to				 * avoid the Kerberos code doing a hostname look-up.				 */				/*				 * XXX fe-auth.c has not been fixed to support PQExpBuffers,				 * so:				 */				if (pg_fe_sendauth(areq, conn, conn->pghost, conn->pgpass,								   conn->errorMessage.data) != STATUS_OK)				{					conn->errorMessage.len = strlen(conn->errorMessage.data);					goto error_return;				}				conn->errorMessage.len = strlen(conn->errorMessage.data);				/*				 * Just make sure that any data sent by pg_fe_sendauth is				 * flushed out.  Although this theoretically could block, it				 * really shouldn't since we don't send large auth responses.				 */				if (pqFlush(conn))					goto error_return;				if (areq == AUTH_REQ_OK)				{					/* We are done with authentication exchange */					conn->status = CONNECTION_AUTH_OK;					/*					 * Set asyncStatus so that PQsetResult will think that					 * what comes back next is the result of a query.  See					 * below.					 */					conn->asyncStatus = PGASYNC_BUSY;				}				/* Look to see if we have more data yet. */				goto keep_going;			}		case CONNECTION_AUTH_OK:			{				/*				 * Now we expect to hear from the backend. A ReadyForQuery				 * message indicates that startup is successful, but we might				 * also get an Error message indicating failure. (Notice				 * messages indicating nonfatal warnings are also allowed by				 * the protocol, as are ParameterStatus and BackendKeyData				 * messages.) Easiest way to handle this is to let				 * PQgetResult() read the messages. We just have to fake it				 * out about the state of the connection, by setting				 * asyncStatus = PGASYNC_BUSY (done above).				 */				if (PQisBusy(conn))					return PGRES_POLLING_READING;				res = PQgetResult(conn);				/*				 * NULL return indicating we have gone to IDLE state is				 * expected				 */				if (res)				{					if (res->resultStatus != PGRES_FATAL_ERROR)						printfPQExpBuffer(&conn->errorMessage,										  libpq_gettext("unexpected message from server during startup\n"));					/*					 * if the resultStatus is FATAL, then conn->errorMessage					 * already has a copy of the error; needn't copy it back.					 * But add a newline if it's not there already, since					 * postmaster error messages may not have one.					 */					if (conn->errorMessage.len <= 0 ||						conn->errorMessage.data[conn->errorMessage.len - 1] != '\n')						appendPQExpBufferChar(&conn->errorMessage, '\n');					PQclear(res);					goto error_return;				}				/* We can release the address list now. */				pg_freeaddrinfo_all(conn->addrlist_family, conn->addrlist);				conn->addrlist = NULL;				conn->addr_cur = NULL;				/* Fire up post-connection housekeeping if needed */				if (PG_PROTOCOL_MAJOR(conn->pversion) < 3)				{					conn->status = CONNECTION_SETENV;					conn->setenv_state = SETENV_STATE_OPTION_SEND;					conn->next_eo = EnvironmentOptions;					return PGRES_POLLING_WRITING;				}				/* Otherwise, we are open for business! */				conn->status = CONNECTION_OK;				return PGRES_POLLING_OK;			}		case CONNECTION_SETENV:			/*			 * Do post-connection housekeeping (only needed in protocol 2.0).			 *			 * We pretend that the connection is OK for the duration of these			 * queries.			 */			conn->status = CONNECTION_OK;			switch (pqSetenvPoll(conn))			{				case PGRES_POLLING_OK:	/* Success */					break;				case PGRES_POLLING_READING:		/* Still going */					conn->status = CONNECTION_SETENV;					return PGRES_POLLING_READING;				case PGRES_POLLING_WRITING:		/* Still going */					conn->status = CONNECTION_SETENV;					return PGRES_POLLING_WRITING;				default:					goto error_return;			}			/* We are open for business! */			conn->status = CONNECTION_OK;			return PGRES_POLLING_OK;		default:			printfPQExpBuffer(&conn->errorMessage,							  libpq_gettext(											"invalid connection state %c, "								 "probably indicative of memory corruption\n"											),							  conn->status);			goto error_return;	}	/* Unreachable */error_return:	/*	 * We used to close the socket at this point, but that makes it awkward	 * for those above us if they wish to remove this socket from their own	 * records (an fd_set for example).  We'll just have this socket closed	 * when PQfinish is called (which is compulsory even after an error, since	 * the connection structure must be freed).	 */	conn->status = CONNECTION_BAD;	return PGRES_POLLING_FAILED;}/* * makeEmptyPGconn *	 - create a PGconn data structure with (as yet) no interesting data */static PGconn *makeEmptyPGconn(void){	PGconn	   *conn;#ifdef WIN32	/*	 * Make sure socket support is up and running. Even though this is done in	 * libpqdll.c, that is only for MSVC and BCC builds and doesn't work for	 * static builds at all, so we have to do it in the main code too.	 */	WSADATA		wsaData;	if (WSAStartup(MAKEWORD(1, 1), &wsaData))		return NULL;	WSASetLastError(0);#endif	conn = (PGconn *) malloc(sizeof(PGconn));	if (conn == NULL)		return conn;	/* Zero all pointers and booleans */	MemSet(conn, 0, sizeof(PGconn));	conn->noticeHooks.noticeRec = defaultNoticeReceiver;	conn->noticeHooks.noticeProc = defaultNoticeProcessor;	conn->status = CONNECTION_BAD;	conn->asyncStatus = PGASYNC_IDLE;	conn->xactStatus = PQTRANS_IDLE;	conn->setenv_state = SETENV_STATE_IDLE;	conn->client_encoding = PG_SQL_ASCII;	conn->std_strings = false;	/* unless server says differently */	conn->verbosity = PQERRORS_DEFAULT;	conn->sock = -1;#ifdef USE_SSL	conn->allow_ssl_try = true;	conn->wait_ssl_try = false;#endif	/*	 * We try to send at least 8K at a time, which is the usual size of pipe	 * buffers on Unix systems.  That way, when we are sending a large amount	 * of data, we avoid incurring extra kernel context swaps for partial	 * bufferloads.  The output buffer is initially made 16K in size, and we	 * try to dump it after accumulating 8K.	 *	 * With the same goal of minimizing context swaps, the input buffer will	 * be enlarged anytime it has less than 8K free, so we initially allocate	 * twice that.	 */	conn->inBufSize = 16 * 1024;	conn->inBuffer = (char *) malloc(conn->inBufSize);	conn->outBufSize = 16 * 1024;	conn->outBuffer = (char *) malloc(conn->outBufSize);	conn->nonblocking = FALSE;	initPQExpBuffer(&conn->errorMessage);	initPQExpBuffer(&conn->workBuffer);	if (conn->inBuffer == NULL ||		conn->outBuffer == NULL ||		conn->errorMessage.data == NULL ||		conn->workBuffer.data == NULL)	{		/* out of memory already :-( */		freePGconn(conn);		conn = NULL;	}	return conn;}/* * freePGconn *	 - free the PGconn data structure * * When changing/adding to this function, see also closePGconn! */static voidfreePGconn(PGconn *conn){	PGnotify   *notify;	pgParameterStatus *pstatus;#ifdef WIN32	WSACleanup();#endif	if (!conn)		return;	pqClearAsyncResult(conn);	/* deallocate result and curTuple */	if (conn->sock >= 0)	{		pqsecure_close(conn);		closesocket(conn->sock);	}	if (conn->pghost)		free(conn->pghost);	if (conn->pghostaddr)		free(conn->pghostaddr);	if (conn->pgport)		free(conn->pgport);	if (conn->pgunixsocket)		free(conn->pgunixsocket);	if (conn->pgtty)		free(conn->pgtty);	if (conn->connect_timeout)		free(conn->connect_timeout);	if (conn->pgoptions)		free(conn->pgoptions);	if (conn->dbName)		free(conn->dbName);	if (conn->pguser)		free(conn->pguser);	if (conn->pgpass)		free(conn->pgpass);	if (conn->sslmode)		free(conn->sslmode);#ifdef KRB5	if (conn->krbsrvname)		free(conn->krbsrvname);#endif	/* Note that conn->Pfdebug is not ours to close or free */	pg_freeaddrinfo_all(conn->addrlist_family, conn->addrlist);	notify = conn->notifyHead;	while (notify != NULL)	{		PGnotify   *prev = notify;		notify = notify->next;		free(prev);	}	pstatus = conn->pstatus;	while (pstatus != NULL)	{		pgParameterStatus *prev = pstatus;		pstatus = pstatus->next;		free(prev);	}	if (conn->lobjfuncs)		free(conn->lobjfuncs);	if (conn->inBuffer)		free(conn->inBuffer);	if (conn->outBuffer)		free(conn->outBuffer);	termPQExpBuffer(&conn->errorMessage);	termPQExpBuffer(&conn->workBuffer);	free(conn);}/* * closePGconn *	 - properly close a connection to the backend * * Release all transient state, but NOT the connection parameters. */static voidclosePGconn(PGconn *conn){	PGnotify   *notify;	pgParameterStatus *pstatus;	/*	 * Note that the protocol doesn't allow us to send Terminate messages	 * during the startup phase.	 */	if (conn->sock >= 0 && conn->status == CONNECTION_OK)	{		/*		 * Try to send "close connection" message to backend. Ignore any		 * error.		 */		pqPutMsgStart('X', false, conn);		pqPutMsgEnd(conn);		pqFlush(conn);	}	/*	 * must reset the blocking status so a possible reconnect will work don't	 * call PQsetnonblocking() because it will fail if it's unable to flush	 * the connection.	 */	conn->nonblocking = FALSE;	/*	 * Close the connection, reset all transient state, flush I/O buffers.	 */	if (conn->sock >= 0)	{		pqsecure_close(conn);		closesocket(conn->sock);	}	conn->sock = -1;	conn->status = CONNECTION_BAD;		/* Well, not really _bad_ - just										 * absent */	conn->asyncStatus = PGASYNC_IDLE;	pqClearAsyncResult(conn);	/* deallocate result and curTuple */	pg_freeaddrinfo_all(conn->addrlist_family, conn->addrlist);	conn->addrlist = NULL;	conn->addr_cur = NULL;	notify = conn->notifyHead;	while (notify != NULL)	{		PGnotify   *prev = notify;		notify = notify->next;		free(prev);	}	conn->notifyHead = NULL;	pstatus = conn->pstatus;	while (pstatus != NULL)	{		pgParameterStatus *prev = pstatus;		pstatus = pstatus->next;		free(prev);	}	conn->pstatus = NULL;	if (conn->lobjfuncs)		free(conn->lobjfuncs);	conn->lobjfuncs = NULL;	conn->inStart = conn->inCursor = conn->inEnd = 0;	conn->outCount = 0;}/* * PQfinish: properly close a connection to the backend. Also frees * the PGconn data structure so it shouldn't be re-used after this. */voidPQfinish(PGconn *conn){	if (conn)	{		closePGconn(conn);		freePGconn(conn);	}}/* * PQreset: resets the connection to the backend by closing the * existing connection and creating a new one. */voidPQreset(PGconn *conn){	if (conn)	{		closePGconn(conn);		if (connectDBStart(conn))			(void) connectDBComplete(conn);	}}/* * PQresetStart: * resets the connection to the backend * closes the existing connection and makes a new one * Returns 1 on success, 0 on failure. */intPQresetStart(PGconn *conn){	if (conn)	{		closePGconn(conn);		return connectDBStart(conn);	}	return 0;}/* * PQresetPoll: * resets the connection to the backend * closes the existing connection and makes a new one */PostgresPollingStatusTypePQresetPoll(PGconn *conn){	if (conn)		return PQconnectPoll(conn);	return PGRES_POLLING_FAILED;}/* * PQcancelGet: get a PGcancel structure corresponding to a connection.

⌨️ 快捷键说明

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