## root/clib/ipcomm.c

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

## DEFINITIONS

This source file includes following definitions.

1. ipc_recv
2. ipc_send

    /* Low level TCP socket routines. These routines are used by both
       client and server API's.
       Rick Smereka, Copyright (C) 1998-2006.

       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 CodeWarrior V4 under Windows 32bit.
       Dec/98, Rick Smereka

       Ported to HP-UX under GNU C 2.8.1.
       Jan/99, Rick Smereka

       Ported to Red Hat Linux 5.2, Jul/99, Rick Smereka

       Ported to Debian Linux. Nov/2002, Rick Smereka

       Changed 'ipc_send' to send the data length before the actual data
       and changed 'ipc_recv' to receive the data length before the
       actual data. Feb/2006, Rick Smereka

       Commented out calls to 'log_file_date' unless there is an error.
       Sep/2006, Rick Smereka */

    #include "stdhead.h"
    #include "flsocket.h"
    #include "ipcomm.h"

    #ifdef OS_WIN32
    int ipc_recv(SOCKET sock, char *buf)
    #endif

    #ifdef OS_UNIX
    int ipc_recv(int sock, char *buf)
    #endif
    {
       /* Receive up to 'IPC_MAXREC' - 1 bytes from the
          socket which is assumed to be open. Function
          returns the number of bytes read upon success,
          zero otherwise. */

       char mname[] = "ipc_recv", *fbuf;
       int charRecv, len, pos = 0, done = FALSE;

       if ((fbuf = (char *)malloc(IPC_SR_BUFSIZE)) == (char *)NULL)
          {
          log_file_date("%s:alloc fail[fbuf]", mname);
          return(FALSE);
          }

       // receive fixed size header wich must contain length of data

    #ifdef OS_WIN32
       charRecv = recv(sock, (LPSTR)fbuf, IPC_HEAD_SIZE, NO_FLAGS);
    #endif

    #ifdef OS_UNIX
       charRecv = recv(sock, fbuf, IPC_HEAD_SIZE, NO_FLAGS);
    #endif

       if (charRecv == SOCKET_ERROR)
          {
          free(fbuf);
          log_file_date("%s:bad rc[-1] from recv[header]", mname);
          return(0);
          }

       if (charRecv != IPC_HEAD_SIZE)
          {
          free(fbuf);
          log_file_date("%s:received improper header size", mname);
          return(0);
          }

       fbuf[IPC_HEAD_SIZE] = EOS;
       // log_file_date("%s:recv header=%s[%d]", mname, fbuf, strlen(fbuf));

       if (!qatoi(fbuf, &len))
          {
          free(fbuf);
          log_file_date("%s:header length is non-numeric", mname);
          return(0);
          }

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

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

            if (charRecv == SOCKET_ERROR)
               {
               free(fbuf);
               log_file_date("%s:bad rc[-1] from recv", mname);
               return(0);
               }

            fbuf[charRecv] = EOS;
            // log_file_date("%s:received %d byte(s)", mname, charRecv);

            if ((strlen(fbuf) + strlen(buf)) >= IPC_MAXREC)
               {
               log_file_date("%s:too much data", mname);
               free(fbuf);
               return(0);
               }

             strncpy(&buf[pos], fbuf, charRecv);

             if (charRecv > 0)
                pos += charRecv;

             buf[pos] = EOS;

             // we are done when we have received all bytes according to header

             if (pos >= len)
                done = TRUE;
             }

       free(fbuf);
       // log_file_date("%s:received total of %d byte(s)", mname, pos);
       return(pos);
    }

    #ifdef OS_WIN32
    int ipc_send(SOCKET sock, char *buf)
    #endif

    #ifdef OS_UNIX
    int ipc_send(int sock, char *buf)
    #endif
    {
       /* Send data to the socket. Function returns the
          number of bytes sent upon success, zero
          otherwise. */

       char *fbuf, header[IPC_HEAD_SIZE + 1], mname[] = "ipc_send";
       int len, charSent, pos = 0, bytesToGo, done = FALSE;
       int chunk;

       len = strlen(buf);

       if (!len)
          return(0);

       // send fixed size header first consisting of data size

       sprintf(header, "%010d", len);
       // log_file_date("%s:header to send is %s[%d]", mname, header, strlen(header));

       if ((charSent = send(sock, header, IPC_HEAD_SIZE, NO_FLAGS)) ==
            SOCKET_ERROR)
          {
          log_file_date("%s:bad rc[%d] from send[header]", mname, charSent);
          return(FALSE);
          }

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

       if (len < IPC_SR_BUFSIZE)
          {
          if ((charSent = send(sock, buf, len, NO_FLAGS)) == SOCKET_ERROR)
             {
             log_file_date("%s:bad rc[%d] from send", mname, charSent);
             return(FALSE);
             }

          return(charSent);
          }

       if ((fbuf = (char *)malloc(IPC_SR_BUFSIZE)) == (char *)NULL)
          {
          log_file_date("%s:alloc fail[fbuf]", mname);
          return(FALSE);
          }

       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;

          strncpy(fbuf, &buf[pos], chunk);
          fbuf[chunk] = EOS;

          if ((charSent = send(sock, fbuf, chunk, NO_FLAGS)) == SOCKET_ERROR)
             {
             pos = 0;
             log_file_date("%s:bad rc[%d] from send", mname, charSent);
             break;
             }

          bytesToGo -= chunk;
          pos += charSent;

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

       free(fbuf);
       //log_file_date("ipc_send:sent total of %d byte(s)", pos);
       return(pos);
    }

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