Connection.cxx
上传用户:sy_wanhua
上传日期:2013-07-25
资源大小:3048k
文件大小:10k
源码类别:

流媒体/Mpeg4/MP4

开发平台:

C/C++

  1. /* ====================================================================
  2.  * The Vovida Software License, Version 1.0 
  3.  * 
  4.  * Copyright (c) 2000 Vovida Networks, Inc.  All rights reserved.
  5.  * 
  6.  * Redistribution and use in source and binary forms, with or without
  7.  * modification, are permitted provided that the following conditions
  8.  * are met:
  9.  * 
  10.  * 1. Redistributions of source code must retain the above copyright
  11.  *    notice, this list of conditions and the following disclaimer.
  12.  * 
  13.  * 2. Redistributions in binary form must reproduce the above copyright
  14.  *    notice, this list of conditions and the following disclaimer in
  15.  *    the documentation and/or other materials provided with the
  16.  *    distribution.
  17.  * 
  18.  * 3. The names "VOCAL", "Vovida Open Communication Application Library",
  19.  *    and "Vovida Open Communication Application Library (VOCAL)" must
  20.  *    not be used to endorse or promote products derived from this
  21.  *    software without prior written permission. For written
  22.  *    permission, please contact vocal@vovida.org.
  23.  *
  24.  * 4. Products derived from this software may not be called "VOCAL", nor
  25.  *    may "VOCAL" appear in their name, without prior written
  26.  *    permission of Vovida Networks, Inc.
  27.  * 
  28.  * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
  29.  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  30.  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
  31.  * NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL VOVIDA
  32.  * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
  33.  * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
  34.  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  35.  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  36.  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
  37.  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  38.  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
  39.  * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
  40.  * DAMAGE.
  41.  * 
  42.  * ====================================================================
  43.  * 
  44.  * This software consists of voluntary contributions made by Vovida
  45.  * Networks, Inc. and many individuals on behalf of Vovida Networks,
  46.  * Inc.  For more information on Vovida Networks, Inc., please see
  47.  * <http://www.vovida.org/>.
  48.  *
  49.  */
  50. static const char* const Connection_cxx_Version =
  51.     "$Id: Connection.cxx,v 1.3 2001/07/18 00:06:11 bko Exp $";
  52. #ifndef __vxworks
  53. #include <errno.h>
  54. #include <unistd.h>
  55. #include <stdio.h>
  56. #include <sys/types.h>
  57. #include <netinet/in.h>
  58. #include <sys/socket.h>
  59. #include <string.h>
  60. #include <fcntl.h>
  61. #include <assert.h>
  62. #ifndef __vxworks
  63. #include <signal.h>
  64. //#include <sys/signal.h>
  65. #endif
  66. #ifndef __vxworks
  67. #include <sys/time.h>
  68. #else
  69. #include "vsock.hxx"
  70. #endif
  71. #include "VNetworkException.hxx"
  72. #include "cpLog.h"
  73. #include "Connection.hxx"
  74. #include "VCondition.h"
  75. bool Connection::_init = false;
  76. void
  77. Connection::initialize()
  78. {
  79.     if (!_init)
  80.     {
  81. #if !defined(__vxworks) && !defined(WIN32)
  82.         // setup SIGPIPE handler
  83.         if (signal(SIGPIPE, SIG_IGN) == SIG_ERR)
  84.             cpLog(LOG_ALERT,
  85.                   "Warning: Can't ignore SIGPIPE, broken pipes will exit program");
  86. #endif
  87.         _init = true;
  88.     }
  89. }
  90. int
  91. Connection::readLine(void* dataRead, size_t maxlen, int& bytesRead) throw (VNetworkException&)
  92. {
  93.     char c;
  94.     int rc, i;
  95.     char* ptr = (char*)dataRead;
  96.     bytesRead = 0;
  97.     for (i = 1; i <= (int)maxlen; i++)
  98.     {
  99.         if ((rc = effRead(&c)) == 1)
  100.         {
  101.             *ptr++ = c;
  102.             bytesRead++;
  103.             if (c == 'n') break;
  104.         }
  105.         else if (rc == 0)
  106.         {
  107.             if ( i == 1) return 0;
  108.             else break;
  109.         }
  110.         else
  111.         {
  112.             return -1;
  113.         }
  114.     }
  115.     *ptr = 0;
  116.     dataRead = ptr;
  117.     return ((i == 1) ? 0 : i);
  118. }
  119. int
  120. Connection::readn(void *dataRead, size_t nchar, int & bRead) throw (VNetworkException&)
  121. {
  122.     size_t nleft;
  123.     ssize_t nread;
  124.     char *ptr = (char*)dataRead;
  125.     nleft = nchar;
  126.     while (nleft > 0)
  127.     {
  128. #ifndef WIN32
  129.         if ((nread = read(_connId, ptr, nleft)) < 0)
  130. #else
  131. if ((nread  =recv(_connId, ptr, nleft, 0)) < 0)
  132. #endif
  133.         {
  134.             if ((errno == EINTR) || (errno == EAGAIN))
  135.             {
  136.                 //cpLog(LOG_DEBUG, "Received EINTR or EAGAIN, keep trying");
  137.                 nread = 0;
  138.             }
  139.             else
  140.             {
  141.                 return -1;
  142.             }
  143.         }
  144.         else if (nread == 0)
  145.         {
  146.             //NO more data
  147.             return 0;
  148.         }
  149.         nleft -= nread;
  150.         ptr += nread;
  151.         bRead += nread;
  152.     }
  153.     return (1);
  154. }
  155. int
  156. Connection::readn(void *dataRead, size_t nchar) throw (VNetworkException&)
  157. {
  158.     if (dataRead == 0)
  159.         return -1;
  160. #ifndef WIN32
  161.     return (read(_connId, static_cast < char* > (dataRead), nchar));
  162. #else
  163.     return (recv(_connId, static_cast<char*>(dataRead), nchar, 0));
  164. #endif
  165. }
  166. void
  167. Connection::writeData(string& data) throw (VNetworkException&)
  168. {
  169.     char *ptr = (char*)data.c_str();
  170.     size_t nleft = data.size();
  171.     writeData(ptr, nleft);
  172. }
  173. void
  174. Connection::writeData(void* data, size_t n) throw (VNetworkException&)
  175. {
  176.     size_t nleft;
  177.     ssize_t nwritten;
  178.     char *ptr = (char*)data;
  179.     nleft = n;
  180.     while (nleft > 0)
  181.     {
  182. #ifndef WIN32
  183.         if ((nwritten = ::write(getConnId(), ptr, nleft)) <= 0)
  184. #else
  185. if ((nwritten = ::send(getConnId(), ptr, nleft, 0)) <= 0)
  186. #endif
  187.         {
  188.             if ((errno == EINTR) || (errno == EAGAIN))
  189.             {
  190.                 //cpLog(LOG_DEBUG, "Received EINTR or EAGAIN, keep trying");
  191.                 nwritten = 0;   //Write again
  192.             }
  193.             else
  194.             {
  195.                 char buf[256];
  196.                 sprintf(buf, "Failed to write data,reason:%s", strerror(errno));
  197.                 cpLog(LOG_ALERT, buf);
  198.                 throw VNetworkException(buf, __FILE__, __LINE__, errno);
  199.             }
  200.         }
  201.         nleft -= nwritten;
  202.         ptr += nwritten;
  203.     }
  204.     //cpLog(LOG_DEBUG, "Bytes written:%d" , nwritten);
  205. }
  206. ssize_t
  207. Connection::effRead(char* ptr)
  208. {
  209.     int readCnt = 0;
  210.     char* readPtr;
  211.     char readBuf[1];
  212.     if (readCnt <= 0)
  213.     {
  214.         while (1)
  215.         {
  216. #ifndef WIN32
  217.             if ((readCnt = ::read(getConnId(), readBuf, sizeof(readBuf))) < 0)
  218. #else
  219.     if ((readCnt = ::recv(getConnId(), readBuf, sizeof(readBuf), 0)) < 0)
  220. #endif
  221.             {
  222.                 if ((errno == EINTR) || (errno == EAGAIN))
  223.                 {
  224.                     //cpLog(LOG_DEBUG, "Received EINTR or EAGAIN, keep trying");
  225.                     vusleep(20);
  226.                     continue;
  227.                 }
  228.                 char buf[256];
  229.                 sprintf(buf, "Failed to read data, reason:%s", strerror(errno));
  230.                 cpLog(LOG_ERR, buf);
  231.                 return -1 ;
  232.             }
  233.             else if (readCnt == 0)
  234.             {
  235.                 return 0;
  236.             }
  237.             readPtr = readBuf;
  238.             break;
  239.         }
  240.     }
  241.     readCnt--;
  242.     *ptr = *readPtr++;
  243.     return 1;
  244. }
  245. #ifdef _WIN32
  246. #define snprintf _snprintf
  247. #endif
  248. string
  249. Connection::getDescription() const
  250. {
  251.     string retStr;
  252.     SA* sa = (SA*) & _connAddr;
  253.     const u_char* p = (const u_char*) & _connAddr.sin_addr;
  254.     switch (sa->sa_family)
  255.     {
  256.         case AF_INET:
  257.         char temp[256];
  258.         snprintf(temp, sizeof(temp), "%d.%d.%d.%d",
  259.                  p[0], p[1], p[2], p[3]);
  260.         char pStr[56];
  261.         sprintf(pStr, ":%d", ntohs(_connAddr.sin_port));
  262.         retStr = temp;
  263.         retStr += pStr;
  264.         return (retStr);
  265.         break;
  266.         default:
  267.         return "Unknown";
  268.         break;
  269.     }
  270.     return ("Unknown");
  271. }
  272. string
  273. Connection::getIp() const
  274. {
  275.     string retStr;
  276.     SA* sa = (SA*) & _connAddr;
  277.     const u_char* p = (const u_char*) & _connAddr.sin_addr;
  278.     switch (sa->sa_family)
  279.     {
  280.         case AF_INET:
  281.         char temp[256];
  282.         snprintf(temp, sizeof(temp), "%d.%d.%d.%d",
  283.                  p[0], p[1], p[2], p[3]);
  284.         retStr = temp;
  285.         return (retStr);
  286.         break;
  287.         default:
  288.         return "Unknown";
  289.         break;
  290.     }
  291.     return ("Unknown");
  292. }
  293. void
  294. Connection::close()
  295. {
  296.     cpLog(LOG_DEBUG, "Closing connection %d", _connId);
  297.     assert(_connId > 2);
  298. #ifndef WIN32
  299.     ::close(_connId);
  300. #else
  301.     int err = closesocket(_connId);
  302.     if (err)
  303.     {
  304.   cpLog(LOG_ERR, "Error closing connection %d", _connId);
  305.     }
  306. #endif
  307.     _live = false;
  308.     _connId = 0;
  309. }
  310. void
  311. Connection::setState()
  312. {
  313. #ifndef WIN32
  314.     if (!_blocking)
  315.     {
  316.         fcntl(_connId, F_SETFL, O_NONBLOCK);
  317.     }
  318. #else
  319.     unsigned long non_blocking = _blocking ? 0 : 1;
  320.     if (ioctlsocket(_connId, FIONBIO, &non_blocking) == SOCKET_ERROR)
  321.     {
  322. cpLog(LOG_ERR, "Error setting Connection FIONBIO: %d", WSAGetLastError());
  323.     }
  324. #endif
  325.     _live = true;
  326. }
  327. bool
  328. Connection::isReadReady(int seconds, int mSecconds) const
  329. {
  330.     fd_set rfds;
  331.     struct timeval tv;
  332.     int retval;
  333.     //cpLog(LOG_DEBUG, "Checking connection %s", getDescription().c_str());
  334.     FD_ZERO(&rfds);
  335.     FD_SET(getConnId(), &rfds);
  336.     tv.tv_sec = seconds;
  337.     tv.tv_usec = mSecconds;
  338.     int connId = getConnId();
  339.     int maxFd = connId;
  340.     retval = select(maxFd + 1, &rfds, NULL, NULL, &tv);
  341.     if (retval > 0 && FD_ISSET(connId, &rfds))
  342.     {
  343.         cpLog(LOG_DEBUG, "Data is ready on fd %d : %s", connId, getDescription().c_str());
  344.         return true;
  345.     }
  346.     return false;
  347. }
  348. void
  349. Connection::deepCopy(const Connection& src, char** bufPtr, int* bufLenPtr)
  350. {
  351.     _connId = src._connId;
  352.     _live = src._live;
  353.     _connAddrLen = src._connAddrLen;
  354.     _connAddr = src._connAddr;
  355.     _blocking = src._blocking;
  356.     _init = src._init;
  357. }
  358. #endif