## root/clib/ssocket.cpp

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

## DEFINITIONS

This source file includes following definitions.

1. ssocket
2. ssocket
3. init
4. server_wait
5. close_client
6. close_all
7. recv_data
8. send_data

    /* Iterative server 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.
       Sep/2000, Rick Smereka

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

    #include "stdhead.h"
    #include "flsocket.h"
    #include "ssocket.h"

    using namespace std;

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

       server_hostname = "";
       server_port = 0;
       server_init = FALSE;
    }

    ssocket::ssocket(int port)
    {
       /* Constructor using port number. After loading port number,
          attempt to initialize the server. */

       server_hostname = "";
       server_port = port;
       server_init = FALSE;
       (void)init(port);
    }

    bool ssocket::init(int port)
    {
       /* Initialize the server for communication. The port
          that the server listens to is expected in 'port'.
          Function returns 'TRUE' upon success,'FALSE' otherwise. */

       char *localHost;
       int err = FALSE;

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

       if (server_init)
          return(FALSE);

       try
          {
          localHost = new char[1024];
          }

       catch(bad_alloc)
          {
          err = TRUE;
          }

       if (err)
          return(FALSE);

       // attempt to resolve the local host name

       if (gethostname(localHost, 1023))
          {
          delete localHost;
          return(FALSE);
          }

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

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

            if (serverSocket == INVALID_SOCKET)
               {
          delete localHost;
               return(FALSE);
               }

            // populate server address structure

       memset(&sockServerAddr, 0,   sizeof(sockServerAddr));
            sockServerAddr.sin_family = AF_INET;
            sockServerAddr.sin_addr.s_addr = INADDR_ANY;
       sockServerAddr.sin_port = htons(port);

            // bind the server socket

    #ifdef OS_WIN32
            if (bind(serverSocket,(LPSOCKADDR)&sockServerAddr,sizeof(sockServerAddr))
               == SOCKET_ERROR)
    #endif

    #ifdef OS_UNIX
            if (bind(serverSocket, (sockaddr *)&sockServerAddr, sizeof(sockServerAddr))
               == SOCKET_ERROR)
    #endif

               {
          delete localHost;
               return(FALSE);
               }

            // listen on port

            if (listen(serverSocket, QUEUE_SIZE) == SOCKET_ERROR)
               {
          delete localHost;
               return(FALSE);
               }

            srvclientSocket = INVALID_SOCKET;
       server_hostname = localHost;
       delete localHost;
       server_init = TRUE;
            return(TRUE);
    }

    bool ssocket::server_wait(void)
    {
       /* Accept a client connection. Function
                    returns 'TRUE' if a client connection
                    was successful, 'FALSE' otherwise. */

    #ifdef OS_WIN32
       int len = sizeof(SOCKADDR);
    #else
       socklen_t len = sizeof(sockClientAddr);
    #endif

       if (!is_init())
          return(FALSE);

            srvclientSocket = INVALID_SOCKET;

    #ifdef OS_WIN32
            srvclientSocket = accept(serverSocket, (LPSOCKADDR)&sockClientAddr,
                                  (LPINT)&len);
    #endif

    #ifdef OS_UNIX
            srvclientSocket = accept(serverSocket, (sockaddr *)&sockClientAddr, &len);
    #endif

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

            return(TRUE);
    }

    bool ssocket::close_client(void)
    {
       /* Close the client socket in use by the server.
          Function returns 'TRUE' upon success, 'FALSE'
          otherwise. */

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

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

    #ifdef OS_UNIX
       close(srvclientSocket);
    #endif

       srvclientSocket = INVALID_SOCKET;
       return(TRUE);
    }

    bool ssocket::close_all(void)
    {
       /* Close all sockets in use by the server.
          Function returns 'TRUE' upon success, 'FALSE'
          otherwise. */

       if (srvclientSocket != INVALID_SOCKET)
    #ifdef OS_WIN32
          if (closesocket(srvclientSocket) == SOCKET_ERROR)
             return(FALSE);
    #endif

    #ifdef OS_UNIX
          close(srvclientSocket);
    #endif

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

    #ifdef OS_UNIX
       close(serverSocket);
    #endif

       return(TRUE);
    }

    int ssocket::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(srvclientSocket, (LPSTR)fbuf, (IPC_SR_BUFSIZE - 1), NO_FLAGS);
    #endif

    #ifdef OS_UNIX
          charRecv = recv(srvclientSocket, 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 ssocket::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(srvclientSocket, 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(srvclientSocket, fbuf.c_str(), chunk, NO_FLAGS)) == SOCKET_ERROR)
                            {
                    pos = 0;
                    break;
                    }

               bytesToGo -= chunk;
               pos += charSent;

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

            return(pos);
    }

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