Index: src/backend/Makefile
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/Makefile,v
retrieving revision 1.75
diff -r1.75 Makefile
17c17
< 	storage tcop utils
---
> 	storage tcop utils pgnet
Index: src/backend/libpq/pqcomm.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/libpq/pqcomm.c,v
retrieving revision 1.126
diff -r1.126 pqcomm.c
45d44
<  *		pq_close		- shutdown libpq at backend exit
84,86d82
< static void pq_close(void);
< 
< 
124d119
< 	on_proc_exit(pq_close, 0);
126,145d120
< 
< 
< /* --------------------------------
<  *		pq_close - shutdown libpq at backend exit
<  *
<  * Note: in a standalone backend MyProcPort will be null,
<  * don't crash during exit...
<  * --------------------------------
<  */
< static void
< pq_close(void)
< {
< 	if (MyProcPort != NULL)
< 	{
< 		close(MyProcPort->sock);
< 		/* make sure any subsequent attempts to do I/O fail cleanly */
< 		MyProcPort->sock = -1;
< 	}
< }
< 
Index: src/backend/postmaster/postmaster.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/postmaster/postmaster.c,v
retrieving revision 1.264
diff -r1.264 postmaster.c
109a110
> #include "pgnet.h"
250d250
< static void processCancelRequest(Port *port, void *pkt);
1057d1056
< 	StartupPacket *packet;
1059,1153c1058
< 	int32		len;
< 	void	   *buf;
< 
< 	if (pq_getbytes((char *) &len, 4) == EOF)
< 	{
< 		elog(DEBUG, "incomplete startup packet");
< 		return STATUS_ERROR;
< 	}
< 
< 	len = ntohl(len);
< 	len -= 4;
< 
< 	if (len < sizeof(len) || len > sizeof(len) + sizeof(StartupPacket))
< 		elog(FATAL, "invalid length of startup packet");
< 
< 	buf = palloc(len);
< 
< 	if (pq_getbytes(buf, len) == EOF)
< 	{
< 		elog(DEBUG, "incomplete startup packet");
< 		return STATUS_ERROR;
< 	}
< 
< 	packet = buf;
< 
< 	/*
< 	 * The first field is either a protocol version number or a special
< 	 * request code.
< 	 */
< 	port->proto = ntohl(packet->protoVersion);
< 
< 	if (port->proto == CANCEL_REQUEST_CODE)
< 	{
< 		processCancelRequest(port, packet);
< 		return 127;				/* XXX */
< 	}
< 
< 	if (port->proto == NEGOTIATE_SSL_CODE && !SSLdone)
< 	{
< 		char		SSLok;
< 
< #ifdef USE_SSL
< 		/* No SSL when disabled or on Unix sockets */
< 		if (!EnableSSL || port->laddr.sa.sa_family != AF_INET)
< 			SSLok = 'N';
< 		else
< 			SSLok = 'S';		/* Support for SSL */
< #else
< 		SSLok = 'N';			/* No support for SSL */
< #endif
< 		if (send(port->sock, &SSLok, 1, 0) != 1)
< 		{
< 			elog(DEBUG, "failed to send SSL negotiation response: %s",
< 				 strerror(errno));
< 			return STATUS_ERROR;	/* close the connection */
< 		}
< 
< #ifdef USE_SSL
< 		if (SSLok == 'S')
< 		{
< 			if (!(port->ssl = SSL_new(SSL_context)) ||
< 				!SSL_set_fd(port->ssl, port->sock) ||
< 				SSL_accept(port->ssl) <= 0)
< 			{
< 				elog(DEBUG, "failed to initialize SSL connection: %s (%m)",
< 					 SSLerrmessage());
< 				return STATUS_ERROR;
< 			}
< 		}
< #endif
< 		/* regular startup packet, cancel, etc packet should follow... */
< 		/* but not another SSL negotiation request */
< 		return ProcessStartupPacket(port, true);
< 	}
< 
< 	/* Could add additional special packet types here */
< 
< 
< 	/* Check we can handle the protocol the frontend is using. */
< 
< 	if (PG_PROTOCOL_MAJOR(port->proto) < PG_PROTOCOL_MAJOR(PG_PROTOCOL_EARLIEST) ||
< 		PG_PROTOCOL_MAJOR(port->proto) > PG_PROTOCOL_MAJOR(PG_PROTOCOL_LATEST) ||
< 		(PG_PROTOCOL_MAJOR(port->proto) == PG_PROTOCOL_MAJOR(PG_PROTOCOL_LATEST) &&
< 		 PG_PROTOCOL_MINOR(port->proto) > PG_PROTOCOL_MINOR(PG_PROTOCOL_LATEST)))
< 		elog(FATAL, "unsupported frontend protocol");
< 
< 	/*
< 	 * Get the parameters from the startup packet as C strings.  The
< 	 * packet destination was cleared first so a short packet has zeros
< 	 * silently added and a long packet is silently truncated.
< 	 */
< 	StrNCpy(port->database, packet->database, sizeof(port->database));
< 	StrNCpy(port->user, packet->user, sizeof(port->user));
< 	StrNCpy(port->options, packet->options, sizeof(port->options));
< 	StrNCpy(port->tty, packet->tty, sizeof(port->tty));
---
> 	int			status;
1155,1157c1060
< 	/* The database defaults to the user name. */
< 	if (port->database[0] == '\0')
< 		StrNCpy(port->database, packet->user, sizeof(port->database));
---
> 	status = pgnet_read_login_packet(port);
1159,1166c1062,1063
< 	/*
< 	 * Truncate given database and user names to length of a Postgres
< 	 * name.  This avoids lookup failures when overlength names are given.
< 	 */
< 	if ((int) sizeof(port->database) >= NAMEDATALEN)
< 		port->database[NAMEDATALEN - 1] = '\0';
< 	if ((int) sizeof(port->user) >= NAMEDATALEN)
< 		port->user[NAMEDATALEN - 1] = '\0';
---
> 	if (status==127)
> 		return status;
1170c1067
< 		elog(FATAL, "no PostgreSQL user name specified in startup packet");
---
> 		pgnet_send_login_nack(port, "no PostgreSQL user name specified in startup packet");
1182c1079
< 			elog(FATAL, "The database system is starting up");
---
> 			pgnet_send_login_nack(port, "The database system is starting up");
1185c1082
< 			elog(FATAL, "The database system is shutting down");
---
> 			pgnet_send_login_nack(port, "The database system is shutting down");
1188c1085
< 			elog(FATAL, "The database system is in recovery mode");
---
> 			pgnet_send_login_nack(port, "The database system is in recovery mode");
1191c1088
< 			elog(FATAL, "Sorry, too many clients already");
---
> 			pgnet_send_login_nack(port, "Sorry, too many clients already");
1203,1257d1099
<  * The client has sent a cancel request packet, not a normal
<  * start-a-new-connection packet.  Perform the necessary processing.
<  * Nothing is sent back to the client.
<  */
< static void
< processCancelRequest(Port *port, void *pkt)
< {
< 	CancelRequestPacket *canc = (CancelRequestPacket *) pkt;
< 	int			backendPID;
< 	long		cancelAuthCode;
< 	Dlelem	   *curr;
< 	Backend    *bp;
< 
< 	backendPID = (int) ntohl(canc->backendPID);
< 	cancelAuthCode = (long) ntohl(canc->cancelAuthCode);
< 
< 	if (backendPID == CheckPointPID)
< 	{
< 		if (DebugLvl)
< 			elog(DEBUG, "processCancelRequest: CheckPointPID in cancel request for process %d", backendPID);
< 		return;
< 	}
< 
< 	/* See if we have a matching backend */
< 
< 	for (curr = DLGetHead(BackendList); curr; curr = DLGetSucc(curr))
< 	{
< 		bp = (Backend *) DLE_VAL(curr);
< 		if (bp->pid == backendPID)
< 		{
< 			if (bp->cancel_key == cancelAuthCode)
< 			{
< 				/* Found a match; signal that backend to cancel current op */
< 				if (DebugLvl)
< 					elog(DEBUG, "processing cancel request: sending SIGINT to process %d",
< 						 backendPID);
< 				kill(bp->pid, SIGINT);
< 			}
< 			else
< 			{
< 				/* Right PID, wrong key: no way, Jose */
< 				if (DebugLvl)
< 					elog(DEBUG, "bad key in cancel request for process %d",
< 						 backendPID);
< 			}
< 			return;
< 		}
< 	}
< 
< 	/* No matching backend */
< 	if (DebugLvl)
< 		elog(DEBUG, "bad pid in cancel request for process %d", backendPID);
< }
< 
< /*
2034c1876
< 	pq_init();					/* initialize libpq to talk to client */
---
> 	pgnet_init(port);			/* initialize libpq to talk to client */
2244a2087,2094
>  /*
>   * This is the remnants of processCancelRequest that relies on the Backend
>   * typedef, and thus is here.
>   */
> int KillBackend(int backendPID, long cancelAuthCode)
> {
> 	Dlelem     *curr;
> 	Backend    *bp;
2245a2096,2118
> 	if (backendPID == CheckPointPID)
> 		return 1;
> 
> 	for (curr = DLGetHead(BackendList); curr; curr = DLGetSucc(curr))
> 	{
> 		bp = (Backend *) DLE_VAL(curr);
> 		if (bp->pid == backendPID)
> 		{
> 			if (bp->cancel_key == cancelAuthCode)
> 			{
> 				/* Found a match; signal that backend to cancel current op */
> 				return kill(bp->pid, SIGINT);
> 			}
> 			else
> 			{
> 				/* Right PID, wrong key: no way, Jose */
> 				return 2;
> 			}
> 		}
> 	}
> 	/* No matching backend */
> 	return 3;
> }
Index: src/backend/tcop/dest.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/tcop/dest.c,v
retrieving revision 1.46
diff -r1.46 dest.c
38d37
< 
42c41,42
< 
---
> #include "pgnet.h"
> #include "miscadmin.h"
92,94c92
< 	Form_pg_attribute *attrs = tupdesc->attrs;
< 	int			natts = tupdesc->natts;
< 	int			i;
---
> 	int has_results = FALSE;
109,125d106
< 			/*
< 			 * if portal name not specified for remote query, use the
< 			 * "blank" portal.
< 			 */
< 			if (pname == NULL)
< 				pname = "blank";
< 
< 			/*
< 			 * send fe info on tuples we're about to send
< 			 */
< 			pq_puttextmessage('P', pname);
< 
< 			/*
< 			 * if this is a retrieve, then we send back the tuple
< 			 * descriptor of the tuples.  "retrieve into" is an exception
< 			 * because no tuples are returned in that case.
< 			 */
127,128c108
< 			{
< 				StringInfoData buf;
---
> 				has_results = TRUE;
130,147c110
< 				pq_beginmessage(&buf);
< 				pq_sendbyte(&buf, 'T'); /* tuple descriptor message type */
< 				pq_sendint(&buf, natts, 2);		/* # of attributes in
< 												 * tuples */
< 
< 				for (i = 0; i < natts; ++i)
< 				{
< 					pq_sendstring(&buf, NameStr(attrs[i]->attname));
< 					pq_sendint(&buf, (int) attrs[i]->atttypid,
< 							   sizeof(attrs[i]->atttypid));
< 					pq_sendint(&buf, attrs[i]->attlen,
< 							   sizeof(attrs[i]->attlen));
< 					if (PG_PROTOCOL_MAJOR(FrontendProtocol) >= 2)
< 						pq_sendint(&buf, attrs[i]->atttypmod,
< 								   sizeof(attrs[i]->atttypmod));
< 				}
< 				pq_endmessage(&buf);
< 			}
---
> 			pgnet_begin_results(MyProcPort, pname, operation, tupdesc, has_results);
207,208d169
< 	char		buf[64];
< 
216,219c177,179
< 			 */
< 			sprintf(buf, "%s%s", commandTag, CommandInfo);
< 			pq_puttextmessage('C', buf);
< 			CommandInfo[0] = '\0';
---
> 			*/
> 			pgnet_set_command_tag(MyProcPort, commandTag);
> 			pgnet_end_results(MyProcPort);
329a290,291
> 			pgnet_set_oid(MyProcPort, lastoid);
> 			pgnet_set_rows_affected(MyProcPort, tuples);
333a296
> 			pgnet_set_rows_affected(MyProcPort, tuples);
Index: src/include/libpq/libpq-be.h
===================================================================
RCS file: /projects/cvsroot/pgsql/src/include/libpq/libpq-be.h,v
retrieving revision 1.27
diff -r1.27 libpq-be.h
59a60
> 	/* this is protocol specific and needs to be moved elsewhere */
60a62
> 
73a76,84
> 	/*
> 	 * Data specific to protocol handling
> 	 */
> 	int operation;
> 	int oid_affected;
> 	int rows_affected;
> 	bool binary_mode;
> 	char *cmd_tag;
> 
