## root/clib/csocket.cpp

/* [<][>][^][v][top][bottom][index][help] */

## DEFINITIONS

This source file includes following definitions.

1. csocket
2. csocket
3. csocket
4. set_active
5. get_active
6. send_receive
7. send_receive
8. close_socket
9. recv_data
10. send_data
11. client_connect

    /* Client socket class for TCP connection oriented IPC.
       Rick Smereka, Copyright (C) 2000-2002.

       This program is free software; you can redistribute it and/or modify
       it under the terms of the GNU General Public License as published by
       the Free Software Foundation; either version 2 of the License, or
       (at your option) any later version.

       This program is distributed in the hope that it will be useful,
       but WITHOUT ANY WARRANTY; without even the implied warranty of
       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
       GNU General Public License for more details.

       You should have received a copy of the GNU General Public License
       along with this program; if not, get a copy via the Internet at
       http://gnu.org/copyleft/gpl.html or write to the Free Software
       Foundation, Inc., 59 Temple Place, Suite 330, Boston,
       MA 02111-1307 USA

       You can contact the author via email at rsmereka@future-lab.com.

       Original version for Unix and Windows 32-bit.
       Aug/2000, Rick Smereka

       Added 'using namespace std'. Dec/2002, RIck Smereka */

    #include "stdhead.h"
    #include "flsocket.h"
    #include "csocket.h"

    using namespace std;

    csocket::csocket()
    {
       // No parameter constructor.

       client_hostname = "";
       client_port = 0;
       client_init = FALSE;
    }

    csocket::csocket(string& host_name, int port)
    {
       // Constructor using string host name and port number.

       if (!set_active(host_name, port))
          {
          client_hostname = "";
          client_port = 0;
          client_init = FALSE;
          }
    }

    csocket::csocket(char *host_name, int port)
    {
       // Constructor using char host name and port number.

       string host;

       if (host_name == (char *)NULL || !strlen(host_name))
          {
          client_hostname = "";
          client_port = 0;
          client_init = FALSE;
          return;
          }

       host = host_name;

       if (!set_active(host, port))
          {
          client_hostname = "";
          client_port = 0;
          client_init = FALSE;
          }
    }

    int csocket::set_active(string& host_name, int port_number)
    {
       /* Set the active server host name and port number.
          Method returns 'TRUE' upon success, 'FALSE'
          otherwise. */

       if (host_name.empty())
          return(FALSE);

       if (port_number <= 0)
          return(FALSE);

       /* load class data, do not check connection */

       client_hostname = host_name;
       client_port = port_number;
       client_init = TRUE;
       return(TRUE);
    }

    int csocket::get_active(string& host_name, int& port_number)
    {
       /* Obtain the current server host name and port number.
          Method returns 'TRUE' upon success with the server
          host name loaded into 'host_name', the server port number will
          be loaded into 'port_number'. Method returns 'FALSE'
          upon failure. */

       if (host_name.empty())
          return(FALSE);

       host_name = "";
       port_number = 0;

       if (!client_init)
          return(FALSE);

       host_name = client_hostname;
       port_number = client_port;
       return(TRUE);
    }

    int csocket::send_receive(string& sbuf, string& rbuf)
    {
       /* Send a command to the current socket server and
          wait for a reply. Method returns 'TRUE' upon
          success with the receive contents loaded into
          'rbuf'. Method returns 'FALSE' upon failure. */

       if (!client_init)
          return(FALSE);

       if (sbuf.empty())
          return(FALSE);

       rbuf = "";

       /* attempt to connect to currently defined server */

       if (!client_connect())
          return(FALSE);

       /* we are connected, send the command string using
          the low level socket send function */

       if (send_data(sbuf) == 0)
          {
          (void)close_socket();
          return(FALSE);
          }

       /* receive reply */

       if (recv_data(rbuf) == 0)
          {
          (void)close_socket();
          return(FALSE);
          }

       (void)close_socket();
       return(TRUE);
    }

    int csocket::send_receive(char *sbuf, string& rbuf)
    {
       // Send a char array and receive a string.

       string sendbuf;

       if (sbuf == (char *)NULL || !strlen(sbuf))
          return(FALSE);

       sendbuf = sbuf;
       return(send_receive(sendbuf, rbuf));
    }

    int csocket::close_socket(void)
    {
       /* Close the socket between client and server.
          Method returns 'TRUE' upon success, 'FALSE'
          otherwise. */

    #ifdef OS_WIN32
       if (closesocket(clientsock) == SOCKET_ERROR)
          return(FALSE);
    #endif

    #ifdef OS_UNIX
       close(clientsock);
    #endif

       return(TRUE);
    }

    int csocket::recv_data(string& buf)
    {
       /* Receive data from the socket which is assumed
          to be open. Method returns the number of bytes
          read upon success with the received data loaded
          into 'buf', zero otherwise. */

       char *fbuf;
       int charRecv, done = FALSE;

       fbuf = new char[IPC_SR_BUFSIZE];
       buf = "";

       while(!done)
            {
    #ifdef OS_WIN32
          charRecv = recv(clientsock, (LPSTR)fbuf, (IPC_SR_BUFSIZE - 1), NO_FLAGS);
    #endif

    #ifdef OS_UNIX
          charRecv = recv(clientsock, fbuf, (IPC_SR_BUFSIZE - 1), NO_FLAGS);
    #endif

            if (charRecv == SOCKET_ERROR)
               {
             delete fbuf;
             return(0);
             }

                    fbuf[charRecv] = EOS;
          buf += fbuf;

            if (charRecv < (IPC_SR_BUFSIZE - 1))
               done = TRUE;
            }

       delete fbuf;
       return(buf.length());
    }

    int csocket::send_data(string& buf)
    {
       /* Send data to the socket. Method returns the
                    number of bytes sent upon success, zero
                    otherwise. */

       string fbuf;
            int len, charSent, pos = 0, bytesToGo, done = FALSE;
            int chunk;

       len = buf.length();

            if (!len)
                    return(0);

            // if less than 'IPC_SR_BUFSIZE' to send, use one shot

            if (len < IPC_SR_BUFSIZE)
               {
          if ((charSent = send(clientsock, buf.c_str(), len, NO_FLAGS)) == SOCKET_ERROR)
                       return(FALSE);

               return(charSent);
               }

            bytesToGo = len;

            // send one buffer length at a time

            while(!done)
               {
               if (bytesToGo > (IPC_SR_BUFSIZE - 1))
                    chunk = IPC_SR_BUFSIZE - 1;
                    else
                            chunk = bytesToGo;

          fbuf = buf.substr(pos, chunk);

          if ((charSent = send(clientsock, fbuf.c_str(), chunk, NO_FLAGS)) == SOCKET_ERROR)
                            {
                    pos = 0;
                    break;
                    }

               bytesToGo -= chunk;
               pos += charSent;

               if (bytesToGo <= 0)
                  done = TRUE;
               }

            return(pos);
    }

    int csocket::client_connect(void)
    {
       /* Use the previously loaded host name and port number to
          connect to the server. Method returns 'TRUE' if the
          connection was successful, 'FALSE' otherwise. */

       if (!client_init)
          return(FALSE);

       // resolve server host name

       lpHostEnt = gethostbyname(client_hostname.c_str());

       if (!lpHostEnt)
          return(FALSE);

            // create the socket

    #ifdef OS_WIN32
            clientsock = socket(PF_INET, SOCK_STREAM, DEFAULT_PROTOCOL);
    #endif

    #ifdef OS_UNIX
            clientsock = socket(AF_INET, SOCK_STREAM, DEFAULT_PROTOCOL);
    #endif

            if (clientsock == INVALID_SOCKET)
               return(FALSE);

       // load client address data

       memset(&sockClientAddr, 0, sizeof(sockClientAddr));
            sockClientAddr.sin_family = AF_INET;
       sockClientAddr.sin_port = htons(client_port);

    #ifdef OS_WIN32
            sockClientAddr.sin_addr = *((LPIN_ADDR)*lpHostEnt->h_addr_list);
    #endif

    #ifdef OS_UNIX
            sockClientAddr.sin_addr.s_addr = ((struct in_addr *)(lpHostEnt->h_addr))->s_addr;
    #endif

            // connect to server

    #ifdef OS_WIN32
            if (connect(clientsock, (LPSOCKADDR)&sockClientAddr, sizeof(sockClientAddr)))
    #endif

    #ifdef OS_UNIX
       if (connect(clientsock, (sockaddr *)&sockClientAddr, sizeof(sockClientAddr)) == SOCKET_ERROR)
    #endif
               return(FALSE);

            return(TRUE);
    }

/* [<][>][^][v][top][bottom][index][help] */