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           rc = rawSendBytes(buffer.getRawDataPtr(), buffer.getBufferSize());
00061           if (this->SOCKET_FAIL != rc)
00062           {
00063             rtn = true;
00064           }
00065           else
00066           {
00067             rtn = false;
00068             logSocketError("Socket sendBytes failed", rc);
00069           }
00070 
00071         }
00072         else
00073         {
00074           LOG_ERROR("Buffer size: %u, is greater than max socket size: %u", buffer.getBufferSize(), this->MAX_BUFFER_SIZE);
00075           rtn = false;
00076         }
00077 
00078       }
00079       else
00080       {
00081         rtn = false;
00082         LOG_WARN("Not connected, bytes not sent");
00083       }
00084 
00085       if (!rtn)
00086       {
00087         this->setConnected(false);
00088       }
00089 
00090       return rtn;
00091 
00092     }
00093 
00094     bool SimpleSocket::receiveBytes(ByteArray & buffer, shared_int num_bytes)
00095     {
00096       int rc = this->SOCKET_FAIL;
00097       bool rtn = false;
00098       shared_int remainBytes = num_bytes;
00099       bool ready, error;
00100 
00101       // Reset the buffer (this is not required since the buffer length should
00102       // ensure that we don't read any of the garbage that may be left over from
00103       // a previous read), but it is good practice.
00104 
00105       memset(&this->buffer_, 0, sizeof(this->buffer_));
00106 
00107       // Doing a sanity check to determine if the byte array buffer is larger than
00108       // what can be sent in the socket.  This should not happen and might be indicative
00109       // of some code synchronization issues between the client and server base.
00110       if (this->MAX_BUFFER_SIZE < (int)buffer.getMaxBufferSize())
00111       {
00112         LOG_WARN("Socket buffer max size: %u, is larger than byte array buffer: %u",
00113             this->MAX_BUFFER_SIZE, buffer.getMaxBufferSize());
00114       }
00115       if (this->isConnected())
00116       {
00117         buffer.init();
00118         while (remainBytes > 0)
00119         {
00120           // Polling the socket results in an "interruptable" socket read.  This
00121           // allows Control-C to break out of a socket read.  Without polling,
00122           // a sig-term is required to kill a program in a socket read function.
00123           if (this->poll(this->SOCKET_POLL_TO, ready, error))
00124           {
00125             if(ready)
00126             {
00127               rc = rawReceiveBytes(this->buffer_, remainBytes);
00128               if (this->SOCKET_FAIL == rc)
00129               {
00130                 this->logSocketError("Socket received failed", rc);
00131                         remainBytes = 0;
00132                 rtn = false;
00133                 break;
00134               }
00135               else if (0 == rc)
00136               {
00137                 LOG_WARN("Recieved zero bytes: %u", rc);
00138                         remainBytes = 0;
00139                 rtn = false;
00140                 break;
00141               }
00142               else
00143               {
00144                 remainBytes = remainBytes - rc;
00145                 LOG_COMM("Byte array receive, bytes read: %u, bytes reqd: %u, bytes left: %u",
00146                     rc, num_bytes, remainBytes);
00147                 buffer.load(&this->buffer_, rc);
00148                 rtn = true;
00149               }
00150             }
00151             else if(error)
00152             {
00153               LOG_ERROR("Socket poll returned an error");
00154               rtn = false;
00155               break;
00156             }
00157             else
00158             {
00159               LOG_ERROR("Uknown error from socket poll");
00160               rtn = false;
00161               break;
00162             }
00163           }
00164           else
00165           {
00166             LOG_COMM("Socket poll timeout, trying again");
00167           }
00168         }
00169       }
00170       else
00171       {
00172         LOG_WARN("Not connected, bytes not sent");
00173         rtn = false;
00174       }
00175 
00176       if (!rtn)
00177       {
00178         this->setConnected(false);
00179       }
00180       return rtn;
00181     }
00182 
00183     bool SimpleSocket::poll(int timeout, bool & ready, bool & error)
00184     {
00185       timeval time;
00186       fd_set read, write, except;
00187       int rc = this->SOCKET_FAIL;
00188       bool rtn = false;
00189       ready = false;
00190       error = false;
00191 
00192       // The select function uses the timeval data structure
00193       time.tv_sec = timeout / 1000;
00194       time.tv_usec = (timeout % 1000) * 1000;
00195 
00196       FD_ZERO(&read);
00197       FD_ZERO(&write);
00198       FD_ZERO(&except);
00199 
00200       FD_SET(this->getSockHandle(), &read);
00201       FD_SET(this->getSockHandle(), &except);
00202 
00203       rc = SELECT(this->getSockHandle() + 1, &read, &write, &except, &time);
00204 
00205       if (this->SOCKET_FAIL != rc)
00206       {
00207         if (0 == rc)
00208         {
00209           rtn = false;
00210         }
00211         else
00212         {
00213           if (FD_ISSET(this->getSockHandle(), &read))
00214           {
00215             ready = true;
00216             rtn = true;
00217           }
00218           else if(FD_ISSET(this->getSockHandle(), &except))
00219           {
00220             error = true;
00221             rtn = true;
00222           }
00223           else
00224           {
00225             LOG_WARN("Select returned, but no flags are set");
00226             rtn = false;
00227           }
00228         }
00229       }
00230       else
00231       {
00232         this->logSocketError("Socket select function failed", rc);
00233         rtn = false;
00234       }
00235 
00236       return rtn;
00237     }
00238 
00239   }  //simple_socket
00240 }  //industrial
00241 


simple_message
Author(s): Shaun Edwards
autogenerated on Fri Aug 28 2015 11:11:56