1
0
mirror of https://github.com/postgres/postgres.git synced 2025-07-14 08:21:07 +03:00

Postgres95 1.01 Distribution - Virgin Sources

This commit is contained in:
Marc G. Fournier
1996-07-09 06:22:35 +00:00
commit d31084e9d1
868 changed files with 242656 additions and 0 deletions

View File

@ -0,0 +1,283 @@
/*-------------------------------------------------------------------------
*
* pqpacket.c--
* routines for reading and writing data packets sent/received by
* POSTGRES clients and servers
*
* Copyright (c) 1994, Regents of the University of California
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/libpq/Attic/pqpacket.c,v 1.1.1.1 1996/07/09 06:21:31 scrappy Exp $
*
*-------------------------------------------------------------------------
*/
/* NOTES
* This is the module that understands the lowest-level part
* of the communication protocol. All of the trickiness in
* this module is for making sure that non-blocking I/O in
* the Postmaster works correctly. Check the notes in PacketRecv
* on non-blocking I/O.
*
* Data Structures:
* Port has two important functions. (1) It records the
* sock/addr used in communication. (2) It holds partially
* read in messages. This is especially important when
* we haven't seen enough to construct a complete packet
* header.
*
* PacketBuf -- None of the clients of this module should know
* what goes into a packet hdr (although they know how big
* it is). This routine is in charge of host to net order
* conversion for headers. Data conversion is someone elses
* responsibility.
*
* IMPORTANT: these routines are called by backends, clients, and
* the Postmaster.
*
*/
#include <stdio.h>
#include <sys/types.h>
#ifndef WIN32
#include <sys/socket.h>
#include <netdb.h>
#include <netinet/in.h>
#else
#include <winsock.h>
#endif /*WIN32 */
#include <fcntl.h>
#include <errno.h>
#include "postgres.h"
#include "miscadmin.h"
#include "utils/elog.h"
#include "storage/ipc.h"
#include "libpq/pqcomm.h" /* where the declarations go */
#include "libpq/libpq.h"
/*
* PacketReceive -- receive a packet on a port.
*
* RETURNS: connection id of the packet sender, if one
* is available.
*
*/
int
PacketReceive(Port *port, /* receive port */
PacketBuf *buf, /* MAX_PACKET_SIZE-worth of buffer space */
bool nonBlocking) /* NON_BLOCKING or BLOCKING i/o */
{
PacketLen max_size = sizeof(PacketBuf);
PacketLen cc; /* character count -- bytes recvd */
PacketLen packetLen; /* remaining packet chars to read */
Addr tmp; /* curr recv buf pointer */
int addrLen = sizeof(struct sockaddr_in);
int hdrLen;
int flag;
int decr;
hdrLen = sizeof(buf->len);
if (nonBlocking == NON_BLOCKING) {
flag = MSG_PEEK;
decr = 0;
} else {
flag = 0;
decr = hdrLen;
}
/*
* Assume port->nBytes is zero unless we were interrupted during
* non-blocking I/O. This first recvfrom() is to get the hdr
* information so we know how many bytes to read. Life would
* be very complicated if we read too much data (buffering).
*/
tmp = ((Addr)buf) + port->nBytes;
if (port->nBytes >= hdrLen) {
packetLen = ntohl(buf->len) - port->nBytes;
}
else {
/* peeking into the incoming message */
cc = recvfrom(port->sock, (char *)&(buf->len), hdrLen, flag,
(struct sockaddr*) &(port->raddr), &addrLen);
if (cc < hdrLen) {
/* if cc is negative, the system call failed */
if (cc < 0) {
return(STATUS_ERROR);
}
/*
* cc == 0 means the connection was broken at the
* other end.
*/
else if (! cc) {
return(STATUS_INVALID);
} else {
/*
* Worst case. We didn't even read in enough data to
* get the header length.
* since we are using a data stream,
* this happens only if the client is mallicious.
*
* Don't save the number of bytes we've read so far.
* Since we only peeked at the incoming message, the
* kernel is going to keep it for us.
*/
return(STATUS_NOT_DONE);
}
} else {
/*
* great. got the header. now get the true length (including
* header size).
*/
packetLen = ntohl(buf->len);
/*
* if someone is sending us junk, close the connection
*/
if (packetLen > max_size) {
port->nBytes = packetLen;
return(STATUS_BAD_PACKET);
}
packetLen -= decr;
tmp += decr - port->nBytes;
}
}
/*
* Now that we know how big it is, read the packet. We read
* the entire packet, since the last call was just a peek.
*/
while (packetLen) {
cc = recvfrom(port->sock, tmp, packetLen, 0,
(struct sockaddr*) &(port->raddr), &addrLen);
if (cc < 0)
return(STATUS_ERROR);
/*
* cc == 0 means the connection was broken at the
* other end.
*/
else if (! cc)
return(STATUS_INVALID);
/*
fprintf(stderr,"expected packet of %d bytes, got %d bytes\n",
packetLen, cc);
*/
tmp += cc;
packetLen -= cc;
/* if non-blocking, we're done. */
if (nonBlocking && packetLen) {
port->nBytes += cc;
return(STATUS_NOT_DONE);
}
}
port->nBytes = 0;
return(STATUS_OK);
}
/*
* PacketSend -- send a single-packet message.
*
* RETURNS: STATUS_ERROR if the write fails, STATUS_OK otherwise.
* SIDE_EFFECTS: may block.
* NOTES: Non-blocking writes would significantly complicate
* buffer management. For now, we're not going to do it.
*
*/
int
PacketSend(Port *port,
PacketBuf *buf,
PacketLen len,
bool nonBlocking)
{
PacketLen totalLen;
int addrLen = sizeof(struct sockaddr_in);
Assert(!nonBlocking);
Assert(buf);
totalLen = len;
len = sendto(port->sock, (Addr) buf, totalLen, /* flags */ 0,
(struct sockaddr *)&(port->raddr), addrLen);
if (len < totalLen) {
(void) sprintf(PQerrormsg,
"FATAL: PacketSend: couldn't send complete packet: errno=%d\n",
errno);
fputs(PQerrormsg, stderr);
return(STATUS_ERROR);
}
return(STATUS_OK);
}
/*
* StartupInfo2PacketBuf -
* convert the fields of the StartupInfo to a PacketBuf
*
*/
/* moved to src/libpq/fe-connect.c */
/*
PacketBuf*
StartupInfo2PacketBuf(StartupInfo* s)
{
PacketBuf* res;
char* tmp;
res = (PacketBuf*)malloc(sizeof(PacketBuf));
res->len = htonl(sizeof(PacketBuf));
res->data[0] = '\0';
tmp= res->data;
strncpy(tmp, s->database, sizeof(s->database));
tmp += sizeof(s->database);
strncpy(tmp, s->user, sizeof(s->user));
tmp += sizeof(s->user);
strncpy(tmp, s->options, sizeof(s->options));
tmp += sizeof(s->options);
strncpy(tmp, s->execFile, sizeof(s->execFile));
tmp += sizeof(s->execFile);
strncpy(tmp, s->tty, sizeof(s->execFile));
return res;
}
*/
/*
* PacketBuf2StartupInfo -
* convert the fields of the StartupInfo to a PacketBuf
*
*/
/* moved to postmaster.c
StartupInfo*
PacketBuf2StartupInfo(PacketBuf* p)
{
StartupInfo* res;
char* tmp;
res = (StartupInfo*)malloc(sizeof(StartupInfo));
res->database[0]='\0';
res->user[0]='\0';
res->options[0]='\0';
res->execFile[0]='\0';
res->tty[0]='\0';
tmp= p->data;
strncpy(res->database,tmp,sizeof(res->database));
tmp += sizeof(res->database);
strncpy(res->user,tmp, sizeof(res->user));
tmp += sizeof(res->user);
strncpy(res->options,tmp, sizeof(res->options));
tmp += sizeof(res->options);
strncpy(res->execFile,tmp, sizeof(res->execFile));
tmp += sizeof(res->execFile);
strncpy(res->tty,tmp, sizeof(res->tty));
return res;
}
*/