Changeset 238 in flair-src for trunk/lib/FlairCore/src/TcpSocket.cpp


Ignore:
Timestamp:
May 15, 2018, 4:41:02 PM (7 years ago)
Author:
Bayard Gildas
Message:

correction sémaphore. bloquant tout ça...

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/lib/FlairCore/src/TcpSocket.cpp

    r231 r238  
    2222#include <fcntl.h>
    2323#include <string.h>
     24#include <system_error>
    2425
    2526using std::string;
     
    3031TcpSocket::TcpSocket(const Object *parent, const std::string name,
    3132                     bool _blockOnSend, bool _blockOnReceive)
    32     : ConnectedSocket(parent, name), isConnected(false) {
     33    : ConnectedSocket(parent, name), socket(0), isConnected(false), isListening(false), distantPort(0), distantAddress() {
    3334  blockOnSend = _blockOnSend;
    3435  blockOnReceive = _blockOnReceive;
     
    3738TcpSocket::~TcpSocket() {
    3839  // Info("Debug: destroying TCP socket %s", ObjectName().c_str());
    39   close(socket);
     40  if (socket) close(socket);
    4041}
    4142
     
    5960  }
    6061
    61   listen(socket, 1);
     62  int ret=listen(socket, 1);
     63  if (ret < 0) {
     64    char errorMsg[256];
     65    Err("select: %s\n", strerror_r(errno, errorMsg, sizeof(errorMsg)));
     66  } else {
     67    isListening=true;
     68  }
    6269}
    6370
    6471TcpSocket *TcpSocket::Accept(Time timeout) {
     72  if (!isListening) throw std::logic_error("Can't call Accept on a non listening socket");
     73
    6574  TcpSocket *acceptedSocket = nullptr;
    6675
    6776  struct timeval tv;
    6877  if (timeout != 0) {
    69     tv.tv_sec = timeout / 1000; // timeout is in ms
    70     tv.tv_usec = (timeout % 1000) * 1000;
     78    tv.tv_sec = timeout / 1000000000;
     79    tv.tv_usec = (timeout % 1000000000) / 1000;
    7180  }
    7281  fd_set rset;
     
    8190    if (ret == 0) {
    8291      // timeout reached
    83       // Err("timeout reached\n");
     92      throw std::runtime_error("Timeout");
    8493    } else {
    8594      // our socket is readable, a new connection can be accepted
     
    8897      sockaddr_in their_addr;
    8998      socklen_t namelen = sizeof(their_addr);
    90       if ((acceptedSocket->socket =
    91                accept(socket, (sockaddr *)&their_addr, &namelen)) < 0) {
    92         char errorMsg[256];
    93         Err("error: %s\n", strerror_r(errno, errorMsg, sizeof(errorMsg)));
     99      ret = accept(socket, (sockaddr *)&their_addr, &namelen);
     100      if (ret < 0) {
    94101        delete acceptedSocket;
    95         acceptedSocket = nullptr;
     102        throw std::system_error(std::error_code(ret, std::generic_category()));
     103      } else {
     104        acceptedSocket->socket = ret;
    96105      }
    97106    }
     
    101110}
    102111
    103 bool TcpSocket::Connect(const unsigned int distantPort,
    104                         const std::string distantAddress, Time timeout) {
     112bool TcpSocket::Connect(const unsigned int _distantPort,
     113                        const std::string _distantAddress, Time timeout) {
    105114  bool success = false;
    106 
     115  bool criticalError=false; //meaning: if true then this socket can't be re-used
     116
     117  //should we open a new socket, close it, or re-use it?
    107118  if (isConnected) {
    108     if (this->distantPort == distantPort &&
    109         this->distantAddress == distantAddress) {
     119    // if already connected to the same host, just return true
     120    if (distantPort == _distantPort && distantAddress == _distantAddress) {
    110121      return true;
    111     } else {
     122    }
     123    // if already connected, but to a different host, close the current socket
     124    else {
     125      isConnected=false;
    112126      close(socket);
    113     }
    114   }
    115   socket = ::socket(AF_INET, SOCK_STREAM, 0);
    116   if (socket == -1)
    117     return false;
     127      socket=0;
     128    }
     129  }
     130  if (!socket) {
     131    socket = ::socket(AF_INET, SOCK_STREAM, 0);
     132    if (socket == -1)
     133      return false;
     134  }
    118135
    119136  sockaddr_in serv_addr;
     
    123140    printf("incorrect network address.");
    124141    close(socket);
     142    socket=0;
    125143    return false;
    126144  }
     
    135153      Err("socket connect: %s\n",
    136154          strerror_r(errno, errorMsg, sizeof(errorMsg)));
    137       success = false;
     155      criticalError = true;
    138156    } else {
    139157      // now block with a timeout
     
    152170        char errorMsg[256];
    153171        Err("select: %s\n", strerror_r(errno, errorMsg, sizeof(errorMsg)));
    154         success = false;
     172        criticalError = true;
    155173      } else {
    156         if (ret == 0) {
    157           // timeout reached
    158           // Err("timeout reached\n");
    159           success = false;
    160         } else {
    161           // something happened on our socket. Check if an error occured
     174        if (ret != 0) { //if ret==0 we're on timeout (nothing to do since success is already set to false)
     175          // something happened on our socket. Check if an error occurred
    162176          int error;
    163177          socklen_t len = sizeof(error);
     
    165179            //char errorMsg[256];
    166180            // Err("getsockopt: %s\n",strerror_r(errno,errorMsg,sizeof(errorMsg)));
    167             success = false;
     181            criticalError = true;
    168182          } else if (error != 0) {
    169183            //char errorMsg[256];
    170184            // Err("socket error: %d(%s)\n",error,strerror_r(error,errorMsg,sizeof(errorMsg)));
    171             success = false;
     185            criticalError = true;
    172186          } else {
    173             if (connect(socket, (sockaddr *)&serv_addr, sizeof(serv_addr)) ==
    174                 -1) {
    175               success = false;
    176             } else {
     187            if (connect(socket, (sockaddr *)&serv_addr, sizeof(serv_addr)) != -1) {
    177188              // Info("connected indeed ^^\n");
    178189              success = true;
     190            } else {
     191              //connect failed
     192              if ((errno != EINPROGRESS) && (errno != EAGAIN)) {
     193                criticalError = true;
     194              }
    179195            }
    180196          }
     
    183199    }
    184200  } else {
    185     success = true; // never reached suprisingly...
     201    success = true; // should never happen since we go non blocking and connect can't be immediate
    186202  }
    187203  // switch back to blocking mode (default)
     
    189205
    190206  if (!success) {
    191     close(socket);
     207    if (criticalError) {
     208      close(socket);
     209      socket=0;
     210    }
     211    isConnected=false;
    192212     //Info("Debug: Connect to %s:%d failed\n", distantAddress.c_str(), distantPort);
    193213    return false;
    194214  } else {
    195215    isConnected = true;
    196     this->distantPort = distantPort;
    197     this->distantAddress = distantAddress;
     216    distantPort = _distantPort;
     217    distantAddress = _distantAddress;
    198218     //Info("Debug: Connect to %s:%d succeeded\n", distantAddress.c_str(), distantPort);
    199219    return true;
     
    208228  } else {
    209229    struct timeval tv;
    210     tv.tv_sec = timeout / 1000; // timeout is in ms
    211     tv.tv_usec = (timeout % 1000) * 1000;
     230    tv.tv_sec = timeout / 1000000000; // timeout is in ns
     231    tv.tv_usec = (timeout % 1000000000) / 1000;
    212232
    213233    setsockopt(socket, SOL_SOCKET, SO_SNDTIMEO, (char *)&tv,
     
    225245  } else {
    226246    struct timeval tv;
    227     tv.tv_sec = timeout / 1000; // timeout is in ms
    228     tv.tv_usec = (timeout % 1000) * 1000;
     247    tv.tv_sec = timeout / 1000000000; // timeout is in ns
     248    tv.tv_usec = (timeout % 1000000000) / 1000;
    229249
    230250    setsockopt(socket, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv,
Note: See TracChangeset for help on using the changeset viewer.