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] */