home *** CD-ROM | disk | FTP | other *** search
- //
- // Connection.cc
- //
- // (c) Copyright 1993, San Diego State University -- College of Sciences
- // (See the COPYRIGHT file for more Copyright information)
- //
- // Implementation of the Connection class
- //
-
- #include "Connection.h"
- #include <errno.h>
- #include <stdio.h>
- #include <sys/types.h>
- #include <sys/socket.h>
- #include <netinet/in.h>
- #include <sys/ioctl.h>
- #include <unistd.h>
-
-
- Connection::Connection()
- {
- sock = -1;
- pos = pos_max = 0;
- }
-
-
- //*************************************************************************
- // Connection::Connection(int socket)
- // PURPOSE:
- // Create a connection from just a socket.
- // PARAMETERS:
- // int socket: obvious!!!!
- //
- Connection::Connection(int socket)
- {
- sock = socket;
-
- int length = sizeof(server);
- if (getpeername(socket, (struct sockaddr *)&server, &length) < 0)
- {
- perror("getpeername");
- }
- pos = pos_max = 0;
- }
-
-
- Connection::~Connection()
- {
- this->close();
- }
-
-
- int Connection::open(int priv)
- {
- if (priv)
- {
- int aport = IPPORT_RESERVED - 1;
-
- sock = rresvport(&aport);
- }
- else
- sock = socket(AF_INET, SOCK_STREAM, 0);
-
- if (sock == NOTOK)
- return NOTOK;
-
- int on = 1;
- setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *) &on, sizeof(on));
- server.sin_family = AF_INET;
-
- pos = pos_max = 0;
- return OK;
- }
-
-
- int Connection::close()
- {
- if (sock >= 0)
- {
- int ret = ::close(sock);
- sock = -1;
- return ret;
- }
- return NOTOK;
- }
-
-
- int Connection::assign_port(int port)
- {
- server.sin_port = htons(port);
- return OK;
- }
-
-
- int Connection::assign_port(char *service)
- {
- struct servent *sp;
-
- sp = getservbyname(service, "tcp");
- if (sp == NULL)
- {
- return NOTOK;
- }
- server.sin_port = sp->s_port;
- return OK;
- }
-
- int Connection::assign_server(dword addr)
- {
- server.sin_addr.s_addr = addr;
- return OK;
- }
-
- int Connection::assign_server(char *name)
- {
- struct hostent *hp;
-
- hp = gethostbyname(name);
- if (hp == NULL)
- {
- return NOTOK;
- }
- memcpy((char *)&server.sin_addr, (char *)hp->h_addr, hp->h_length);
- return OK;
- }
-
-
- int Connection::connect()
- {
- if (::connect(sock, (struct sockaddr *)&server, sizeof(server)) == NOTOK)
- {
- return NOTOK;
- }
- return OK;
- }
-
-
- int Connection::bind()
- {
- if (::bind(sock, (struct sockaddr *)&server, sizeof(server)) == NOTOK)
- {
- return NOTOK;
- }
- return OK;
- }
-
-
- int Connection::get_port()
- {
- int length;
-
- if (getsockname(sock, (struct sockaddr *)&server, &length) == NOTOK)
- {
- return NOTOK;
- }
- return ntohs(server.sin_port);
- }
-
-
- int Connection::listen(int n)
- {
- return ::listen(sock, n);
- }
-
-
- Connection *Connection::accept(int priv)
- {
- int newsock;
-
- while (TRUE)
- {
- newsock = ::accept(sock, (struct sockaddr *)0, (int *)0);
- if (newsock == NOTOK && errno == EINTR)
- continue;
- break;
- }
- if (newsock == NOTOK)
- return (Connection *)0;
-
- Connection *newconnect = new Connection;
- newconnect->sock = newsock;
-
- int length = sizeof(newconnect->server);
- getpeername(newsock, (struct sockaddr *)&newconnect->server, &length);
-
- if (priv && newconnect->server.sin_port >= IPPORT_RESERVED)
- {
- delete newconnect;
- return (Connection *)0;
- }
-
- return newconnect;
- }
-
-
- //*************************************************************************
- // Connection *Connection::accept_privileged()
- // PURPOSE:
- // Accept in incoming connection but only if it is from a
- // privileged port
- //
- Connection * Connection::accept_privileged()
- {
- return accept(1);
- }
-
-
- //*************************************************************************
- // METHOD int Connection::write(char *buffer, int length)
- // PURPOSE:
- // Write <nbytes> bytes from <buffer> to file sock. This will
- // take care of problems where write will return without having
- // written everything in the buffer.
- // PARAMETERS:
- // char *buffer: The buffer to write.
- // int nbytes: The number of bytes to write from <buffer>.
- // RETURN VALUE:
- // Returns number of bytes actually written. If there was an
- // error it returns -1.
- // SIDE EFFECTS:
- // None
- // ASSUMPTIONS:
- // None
- // FUNCTIONS USED:
- // write()
- // ALGORYTHM:
- // Stevens p. 279
- //
- int Connection::write(char *buffer, int length)
- {
- int nleft, nwritten;
-
- nleft = length;
- while (nleft > 0)
- {
- nwritten = ::write(sock, buffer, nleft);
- if (nwritten <= 0)
- return nwritten;
- nleft -= nwritten;
- buffer += nwritten;
- }
- return length - nleft;
- }
-
-
- //*************************************************************************
- // METHOD int Connection::write(char *buffer)
- // PURPOSE:
- // This is identical to the other write except that the length of the
- // buffer is not passed. The buffer is assumed to be NULL terminated.
- // PARAMETERS:
- // char *buffer: The buffer to write.
- // RETURN VALUE:
- // Returns number of bytes actually written. If there was an
- // error it returns -1.
- //
- int Connection::write(char *buffer)
- {
- return write(buffer, strlen(buffer));
- }
-
-
- //*************************************************************************
- // int Connection::read(char *buffer, int length)
- // PURPOSE:
- // Read <length> bytes from the current TCP connection. We will
- // not return until we have all the data we are waiting for
- // unless there was an error
- // PARAMETERS:
- // char *buffer: Buffer to read the data into
- // int length: The number of bytes to read into the buffer
- // RETURN VALUE:
- // The actual number of bytes read. NOTOK if an error occured.
- // ASSUMPTIONS:
- // The connection has been previously established.
- // FUNCTIONS USED:
- // read()
- // ALGORYTHM:
- // Stevens p. 279
- //
- int Connection::read(char *buffer, int length)
- {
- int nleft, nread;
-
- nleft = length;
- while (nleft > 0)
- {
- nread = ::read(sock, buffer, nleft);
- if (nread < 0 && errno == EINTR)
- continue;
- else if (nread < 0)
- {
- perror("read");
- return nread;
- }
- else if (nread == 0)
- return -1; // End of file/stream
-
- nleft -= nread;
- buffer += nread;
- }
- return length - nleft;
- }
-
-
- //***************************************************************************
- // char *Connection::read_line(char *buffer, int maxlength)
- // PURPOSE:
- // Read a line of text, terminated by CR and or LF.
- //
- char *Connection::read_line(char *buffer, int maxlength)
- {
- while (maxlength > 0)
- {
- int ch = get_char();
- if (ch < 0)
- return (char *) 0;
- else if (ch == '\r')
- continue;
- else if (ch == '\n')
- break;
- else
- {
- *buffer++ = ch;
- maxlength--;
- }
- }
- *buffer = '\0';
- return buffer;
- }
-
-
- //*************************************************************************
- // int Connection::read_partial(char *buffer, int maxlength)
- // PURPOSE:
- // Read at most <maxlength> from the current TCP connection.
- // This is equivalent to the workings of the standard read()
- // system call
- // PARAMETERS:
- // char *buffer: Buffer to read the data into
- // int maxlength: Maximum number of bytes to read into the buffer
- // RETURN VALUE:
- // The actual number of bytes read in.
- // ASSUMPTIONS:
- // The connection has been previously established.
- // FUNCTIONS USED:
- // read()
- //
- int Connection::read_partial(char *buffer, int maxlength)
- {
- return ::read(sock, buffer, maxlength);
- }
-
-
- //*************************************************************************
- // int Connection::bytes_available()
- // PURPOSE:
- // Check to see how many bytes can be read from the connection
- // currently
- // RETURN VALUE:
- // The number of bytes available.
- //
- int Connection::bytes_available()
- {
- int count = -1;
-
- ioctl(sock, FIONREAD, (char *) &count);
-
- return count;
- }
-
-
- //*************************************************************************
- // char * Connection::socket_as_string()
- // PURPOSE:
- // Return the numeric ASCII equivalent of the socket number.
- // This is needed to pass the socket to another program
- //
- char * Connection::socket_as_string()
- {
- char buffer[20];
-
- sprintf(buffer, "%d", sock);
- return strdup(buffer);
- }
-
-
- //*************************************************************************
- // int Connection::get_socket()
- // PURPOSE:
- // Return the current socket number
- //
- int Connection::get_socket()
- {
- return sock;
- }
-
-
- //*************************************************************************
- // int Connection::isopen()
- // PURPOSE:
- // Return true if the connection is open
- //
- int Connection::isopen()
- {
- return sock >= 0;
- }
-
-
- //*************************************************************************
- // int Connection::get_char()
- //
- int Connection::get_char()
- {
- if (pos >= pos_max)
- {
- pos_max = read_partial(buffer, BUFFER_SIZE);
- pos = 0;
- if (pos_max <= 0)
- return -1;
- }
- return buffer[pos++];
- }
-
-
-