www.pudn.com > udt.rar > socket.cpp


/*****************************************************************************
UDT "C" socket API
*****************************************************************************/

#ifdef CAPI

#include 
#include 
#include 
#include 
#include 
#include 

#include "udt.h"

const static char* const g_pcSysLibPath = "libc.so.6";
const CSysLib g_SysLib;

CSysLib::CSysLib()
{
   m_pHSysSockLib = dlopen(g_pcSysLibPath, RTLD_NOW);
   if (NULL == m_pHSysSockLib)
   {
      cerr << "UDT: cannot load " << g_pcSysLibPath << endl;
      exit(0);
   }

   socket = (int(*)(int, int, int))dlsym(m_pHSysSockLib, "socket");
   bind = (int(*)(int, const struct sockaddr*, unsigned int))dlsym(m_pHSysSockLib, "bind");
   listen = (int(*)(int, int))dlsym(m_pHSysSockLib, "listen");
   accept = (int(*)(int, struct sockaddr*, socklen_t*))dlsym(m_pHSysSockLib, "accept");
   connect = (int(*)(int, const struct sockaddr*, socklen_t))dlsym(m_pHSysSockLib, "connect");
   close = (int(*)(int))dlsym(m_pHSysSockLib, "close");
   shutdown = (int(*)(int, int))dlsym(m_pHSysSockLib, "shutdown");
   send = (ssize_t(*)(int, const void*, unsigned int, int))dlsym(m_pHSysSockLib, "send");
   recv = (ssize_t(*)(int, void*, unsigned int, int))dlsym(m_pHSysSockLib, "recv");
   write = (ssize_t(*)(int, const void*, size_t))dlsym(m_pHSysSockLib, "write");
   read = (ssize_t(*)(int, void*, size_t))dlsym(m_pHSysSockLib, "read");
   writev = (int(*)(int, const struct iovec*, size_t))dlsym(m_pHSysSockLib, "writev");
   readv = (int(*)(int, const struct iovec*, size_t))dlsym(m_pHSysSockLib, "readv");
   sendfile = (ssize_t(*)(int, int, off_t*, size_t))dlsym(m_pHSysSockLib, "sendfile");
   getpeername = (int(*)(int, struct sockaddr*, socklen_t*))dlsym(m_pHSysSockLib, "getpeername");
   getsockname = (int(*)(int, struct sockaddr*, socklen_t*))dlsym(m_pHSysSockLib, "getsockname");
   getsockopt = (int(*)(int, int, int, void*, socklen_t*))dlsym(m_pHSysSockLib, "getsockopt");
   setsockopt = (int(*)(int, int, int, const void*, socklen_t))dlsym(m_pHSysSockLib, "setsockopt");
   fcntl = (int(*)(int, int, ...))dlsym(m_pHSysSockLib, "fcntl");
   select = (int(*)(int, fd_set*, fd_set*, fd_set*, struct timeval*))dlsym(m_pHSysSockLib, "select");
}

CSysLib::~CSysLib()
{
   dlclose(m_pHSysSockLib);
}


extern "C" 
{

int socket(int af, int type, int flag)
{
   if (SOCK_STREAM == type)
      return CUDT::socket(af, type, flag);

   return (*g_SysLib.socket)(af, type, flag);
}

int bind(int u, const struct sockaddr* name, unsigned int namelen)
{
   if (CUDT::isUSock(u))
      return CUDT::bind(u, name, namelen);

   return (*g_SysLib.bind)(u, name, namelen);
}

int listen(int u, int backlog)
{
   if (CUDT::isUSock(u))
      return CUDT::listen(u, backlog);

   return (*g_SysLib.listen)(u, backlog);
}

int accept(int u, struct sockaddr* addr, socklen_t* addrlen)
{
   if (CUDT::isUSock(u))
      return CUDT::accept(u, addr, (int*)addrlen);

   return (*g_SysLib.accept)(u, addr, addrlen);
}

int connect(int u, const struct sockaddr* name, socklen_t namelen)
{
   if (CUDT::isUSock(u))
      return CUDT::connect(u, name, namelen);

   return (*g_SysLib.connect)(u, name, namelen);
}

int close(int u)
{
   if (CUDT::isUSock(u))
      return CUDT::close(u);

   return (*g_SysLib.close)(u);
}

int getpeername(int u, struct sockaddr* name, socklen_t* namelen)
{
   if (CUDT::isUSock(u))
      return CUDT::getpeername(u, name, (int*)namelen);

   return (*g_SysLib.getpeername)(u, name, namelen);
}

int getsockname(int u, struct sockaddr* name, socklen_t* namelen)
{
   if (CUDT::isUSock(u))
      return CUDT::getsockname(u, name, (int*)namelen);

   return (*g_SysLib.getsockname)(u, name, namelen);
}

int getsockopt(int u, int level, int optname, void* optval, socklen_t* optlen)
{
   if (!CUDT::isUSock(u))
      return (*g_SysLib.getsockopt)(u, level, optname, optval, optlen);

   switch (optname)
   {
   case SO_SNDBUF:
      return CUDT::getsockopt(u, level, UDT_SNDBUF, optval, (int*)optlen);

   case SO_RCVBUF:
      return CUDT::getsockopt(u, level, UDT_RCVBUF, optval, (int*)optlen);

   case SO_LINGER:
      return CUDT::getsockopt(u, level, UDT_LINGER, optval, (int*)optlen);

   default:
      return 0;
   }
}

int setsockopt(int u, int level, int optname, const void* optval, socklen_t optlen)
{
   if (!CUDT::isUSock(u))
      return (*g_SysLib.setsockopt)(u, level, optname, optval, optlen);

   switch (optname)
   {
   case SO_SNDBUF:
      return CUDT::setsockopt(u, level, UDT_SNDBUF, optval, optlen);

   case SO_RCVBUF:
      return CUDT::setsockopt(u, level, UDT_RCVBUF, optval, optlen);

   case SO_LINGER:
      return CUDT::setsockopt(u, level, UDT_LINGER, optval, optlen);

   default:
      return 0;
   }
}

int fcntl(int fd, int cmd, ...)
{
   va_list ap;
   long arg;
   flock* lock;

   switch (cmd)
   {
   case F_DUPFD:
   case F_GETFD:
   case F_GETFL:
   case F_GETOWN:
   case F_SETOWN:
   //case F_GETSIG:
   //case F_SETSIG:
      return (*g_SysLib.fcntl)(fd, cmd);

   case F_SETFD:
   case F_SETFL:
      va_start(ap, cmd);
      arg = va_arg(ap, long);
      va_end(ap);

      if (CUDT::isUSock(fd))
      {
         if ((cmd == F_SETFL) && (arg == O_NONBLOCK))
         {
            bool syn = false;
            CUDT::setsockopt(fd, 0, UDT_SNDSYN, &syn, sizeof(bool));
            CUDT::setsockopt(fd, 0, UDT_RCVSYN, &syn, sizeof(bool));
            return 0;
         }
         return -1;
      }

      return (*g_SysLib.fcntl)(fd, cmd, arg);

   case F_GETLK:
   case F_SETLK:
   case F_SETLKW:
      va_start(ap, cmd);
      lock = va_arg(ap, flock*);
      va_end(ap);

      return (*g_SysLib.fcntl)(fd, cmd, lock);

   default:
      return -1;
   }
}

int shutdown(int u, int how)
{
   if (CUDT::isUSock(u))
      return CUDT::shutdown(u, how);

   return (*g_SysLib.shutdown)(u, how);
}

ssize_t send(int u, const void* buf, unsigned int len, int flags)
{
   if (CUDT::isUSock(u))
      return CUDT::send(u, (char*)buf, len, flags, NULL, NULL);

   return (*g_SysLib.send)(u, buf, len, flags);
}

ssize_t recv(int u, void* buf, unsigned int len, int flags)
{
   if (CUDT::isUSock(u))
      return CUDT::recv(u, (char*)buf, len, flags, NULL, NULL);

   return (*g_SysLib.recv)(u, buf, len, flags);
}

ssize_t sendfile(int out_fd, int in_fd, off_t *offset, size_t count)
{
   if (!CUDT::isUSock(out_fd))
      return (*g_SysLib.sendfile)(out_fd, in_fd, offset, count);

   const unsigned __int32 unitsize = 367000;
   unsigned __int32 currsize = 0;
   char* buf = new char[unitsize];

   if (-1 == lseek(in_fd, *offset, SEEK_SET))
      return -1;

   while (count > currsize)
   {
      __int32 realsize = 0;
      __int32 handle;

      if (-1 == (realsize = (*g_SysLib.read)(in_fd, buf, unitsize)))
         break;

      if (-1 == CUDT::send(out_fd, buf, realsize, 0, &handle, NULL))
         break;

      currsize += realsize;
   }

   delete [] buf;

   *offset += currsize;

   if (0 == currsize)
      return -1;
   return currsize;
}

int select(int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout)
{
   // don't support select currently.

   cerr << "UDT: unable to execute select." << endl;
   exit(0);
}

}

#endif