simple_socket.cpp
Go to the documentation of this file.
00001 /*
00002  * Software License Agreement (BSD License)
00003  *
00004  * Copyright (c) 2011, Yaskawa America, Inc.
00005  * All rights reserved.
00006  *
00007  * Redistribution and use in source and binary forms, with or without
00008  * modification, are permitted provided that the following conditions are met:
00009  *
00010  *       * Redistributions of source code must retain the above copyright
00011  *       notice, this list of conditions and the following disclaimer.
00012  *       * Redistributions in binary form must reproduce the above copyright
00013  *       notice, this list of conditions and the following disclaimer in the
00014  *       documentation and/or other materials provided with the distribution.
00015  *       * Neither the name of the Yaskawa America, Inc., nor the names
00016  *       of its contributors may be used to endorse or promote products derived
00017  *       from this software without specific prior written permission.
00018  *
00019  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00020  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00021  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00022  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
00023  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00024  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00025  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00026  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00027  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00028  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00029  * POSSIBILITY OF SUCH DAMAGE.
00030  */
00031 
00032 #ifndef FLATHEADERS
00033 #include "simple_message/socket/simple_socket.h"
00034 #include "simple_message/log_wrapper.h"
00035 #else
00036 #include "simple_socket.h"
00037 #include "log_wrapper.h"
00038 #endif
00039 
00040 using namespace industrial::byte_array;
00041 using namespace industrial::shared_types;
00042 
00043 namespace industrial
00044 {
00045   namespace simple_socket
00046   {
00047 
00048     bool SimpleSocket::sendBytes(ByteArray & buffer)
00049     {
00050       int rc = this->SOCKET_FAIL;
00051       bool rtn = false;
00052 
00053       if (this->isConnected())
00054       {
00055         // Nothing restricts the ByteArray from being larger than the what the socket
00056         // can handle.
00057         if (this->MAX_BUFFER_SIZE > (int)buffer.getBufferSize())
00058         {
00059 
00060           // copy to local array, since ByteArray no longer supports
00061           // direct pointer-access to data values
00062           std::vector<char> localBuffer;
00063           buffer.copyTo(localBuffer);
00064           rc = rawSendBytes(&localBuffer[0], localBuffer.size());
00065           if (this->SOCKET_FAIL != rc)
00066           {
00067             rtn = true;
00068           }
00069           else
00070           {
00071             rtn = false;
00072             logSocketError("Socket sendBytes failed", rc, errno);
00073           }
00074 
00075         }
00076         else
00077         {
00078           LOG_ERROR("Buffer size: %u, is greater than max socket size: %u", buffer.getBufferSize(), this->MAX_BUFFER_SIZE);
00079           rtn = false;
00080         }
00081 
00082       }
00083       else
00084       {
00085         rtn = false;
00086         LOG_WARN("Not connected, bytes not sent");
00087       }
00088 
00089       if (!rtn)
00090       {
00091         this->setConnected(false);
00092       }
00093 
00094       return rtn;
00095 
00096     }
00097 
00098     bool SimpleSocket::receiveBytes(ByteArray & buffer, shared_int num_bytes)
00099     {
00100       int rc = this->SOCKET_FAIL;
00101       bool rtn = false;
00102       shared_int remainBytes = num_bytes;
00103       bool ready, error;
00104 
00105       // Reset the buffer (this is not required since the buffer length should
00106       // ensure that we don't read any of the garbage that may be left over from
00107       // a previous read), but it is good practice.
00108 
00109       memset(&this->buffer_, 0, sizeof(this->buffer_));
00110 
00111       // Doing a sanity check to determine if the byte array buffer is smaller than
00112       // what can be received by the socket.
00113       if (this->MAX_BUFFER_SIZE > buffer.getMaxBufferSize())
00114       {
00115         LOG_WARN("Socket buffer max size: %u, is larger than byte array buffer: %u",
00116             this->MAX_BUFFER_SIZE, buffer.getMaxBufferSize());
00117       }
00118       if (this->isConnected())
00119       {
00120         buffer.init();
00121         while (remainBytes > 0)
00122         {
00123           // Polling the socket results in an "interruptable" socket read.  This
00124           // allows Control-C to break out of a socket read.  Without polling,
00125           // a sig-term is required to kill a program in a socket read function.
00126           if (this->rawPoll(this->SOCKET_POLL_TO, ready, error))
00127           {
00128             if(ready)
00129             {
00130               rc = rawReceiveBytes(this->buffer_, remainBytes);
00131               if (this->SOCKET_FAIL == rc)
00132               {
00133                 this->logSocketError("Socket received failed", rc, errno);
00134                         remainBytes = 0;
00135                 rtn = false;
00136                 break;
00137               }
00138               else if (0 == rc)
00139               {
00140                 LOG_WARN("Recieved zero bytes: %u", rc);
00141                         remainBytes = 0;
00142                 rtn = false;
00143                 break;
00144               }
00145               else
00146               {
00147                 remainBytes = remainBytes - rc;
00148                 LOG_COMM("Byte array receive, bytes read: %u, bytes reqd: %u, bytes left: %u",
00149                     rc, num_bytes, remainBytes);
00150                 buffer.load(&this->buffer_, rc);
00151                 rtn = true;
00152               }
00153             }
00154             else if(error)
00155             {
00156               LOG_ERROR("Socket poll returned an error");
00157               rtn = false;
00158               break;
00159             }
00160             else
00161             {
00162               LOG_ERROR("Uknown error from socket poll");
00163               rtn = false;
00164               break;
00165             }
00166           }
00167           else
00168           {
00169             LOG_COMM("Socket poll timeout, trying again");
00170           }
00171         }
00172       }
00173       else
00174       {
00175         LOG_WARN("Not connected, bytes not sent");
00176         rtn = false;
00177       }
00178 
00179       if (!rtn)
00180       {
00181         this->setConnected(false);
00182       }
00183       return rtn;
00184     }
00185 
00186   }  //simple_socket
00187 }  //industrial
00188 


simple_message
Author(s): Shaun Edwards
autogenerated on Tue Jan 17 2017 21:10:02