| 
							- /*
 - Copyright (C) 2008-2011 Romain Moret at Grame
 - 
 - This program is free software; you can redistribute it and/or modify
 - it under the terms of the GNU General Public License as published by
 - the Free Software Foundation; either version 2 of the License, or
 - (at your option) any later version.
 - 
 - This program is distributed in the hope that it will be useful,
 - but WITHOUT ANY WARRANTY; without even the implied warranty of
 - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 - GNU General Public License for more details.
 - 
 - You should have received a copy of the GNU General Public License
 - along with this program; if not, write to the Free Software
 - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 - 
 - */
 - 
 - #include "JackNetUnixSocket.h"
 - #include "JackError.h"
 - 
 - #include <unistd.h>
 - #include <fcntl.h>
 - 
 - using namespace std;
 - 
 - namespace Jack
 - {
 -     //utility *********************************************************************************************************
 -     int GetHostName(char * name, int size)
 -     {
 -         if (gethostname(name, size) == SOCKET_ERROR) {
 -             jack_error("Can't get 'hostname' : %s", strerror(NET_ERROR_CODE));
 -             strcpy(name, "default");
 -             return SOCKET_ERROR;
 -         }
 -         return 0;
 -     }
 - 
 -     //construct/destruct***********************************************************************************************
 -     JackNetUnixSocket::JackNetUnixSocket()
 -     {
 -         fSockfd = 0;
 -         fPort = 0;
 -         fTimeOut = 0;
 -         fSendAddr.sin_family = AF_INET;
 -         fSendAddr.sin_addr.s_addr = htonl(INADDR_ANY);
 -         memset(&fSendAddr.sin_zero, 0, 8);
 -         fRecvAddr.sin_family = AF_INET;
 -         fRecvAddr.sin_addr.s_addr = htonl(INADDR_ANY);
 -         memset(&fRecvAddr.sin_zero, 0, 8);
 -     }
 - 
 -     JackNetUnixSocket::JackNetUnixSocket(const char* ip, int port)
 -     {
 -         fSockfd = 0;
 -         fPort = port;
 -         fTimeOut = 0;
 -         fSendAddr.sin_family = AF_INET;
 -         fSendAddr.sin_port = htons(port);
 -         inet_aton(ip, &fSendAddr.sin_addr);
 -         memset(&fSendAddr.sin_zero, 0, 8);
 -         fRecvAddr.sin_family = AF_INET;
 -         fRecvAddr.sin_port = htons(port);
 -         fRecvAddr.sin_addr.s_addr = htonl(INADDR_ANY);
 -         memset(&fRecvAddr.sin_zero, 0, 8);
 -     }
 - 
 -     JackNetUnixSocket::JackNetUnixSocket(const JackNetUnixSocket& socket)
 -     {
 -         fSockfd = 0;
 -         fTimeOut = 0;
 -         fPort = socket.fPort;
 -         fSendAddr = socket.fSendAddr;
 -         fRecvAddr = socket.fRecvAddr;
 -     }
 - 
 -     JackNetUnixSocket::~JackNetUnixSocket()
 -     {
 -         Close();
 -     }
 - 
 -     JackNetUnixSocket& JackNetUnixSocket::operator=(const JackNetUnixSocket& socket)
 -     {
 -         if (this != &socket) {
 -             fSockfd = 0;
 -             fPort = socket.fPort;
 -             fSendAddr = socket.fSendAddr;
 -             fRecvAddr = socket.fRecvAddr;
 -         }
 -         return *this;
 -     }
 - 
 -     //socket***********************************************************************************************************
 -     int JackNetUnixSocket::NewSocket()
 -     {
 -         if (fSockfd) {
 -             Close();
 -             Reset();
 -         }
 -         fSockfd = socket(AF_INET, SOCK_DGRAM, 0);
 - 
 -         /* Enable address reuse */
 -         int res, on = 1;
 -     #ifdef __APPLE__
 -         if ((res = setsockopt(fSockfd, SOL_SOCKET, SO_REUSEPORT, &on, sizeof(on))) < 0) {
 -     #else
 -         if ((res = setsockopt(fSockfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on))) < 0) {
 -     #endif
 -             StrError(NET_ERROR_CODE);
 -         }
 -         
 -         int tos = 0;       /* see <netinet/in.h> */
 -         
 -         /*
 -         DSCP Field Hex/Bin/Dec	Layer 2 Prio	Traffic Type	Acronym	WMM Access Category
 -         0x38 / 111000 / 56	7	Network Control	NC	AC_VO
 -         0x30 / 110000 / 48	6	Voice	VO	AC_VO
 -         0x28 / 101000 / 40	5	Video	VI	AC_VI
 -         0x20 / 100000 / 32	4	Controlled Load	CL	AC_VI
 -         0x18 / 011000 / 24	3	Excellent Effort	EE	AC_BE
 -         0x10 / 010000 / 16	2	Spare	--	AC_BK
 -         0x08 / 001000 / 8	1	Background	BK	AC_BK
 -         0x00 / 000000 / 0	0	Best Effort	BE	AC_BE
 -         */
 -         
 -         socklen_t len = sizeof(tos);
 -         
 -         res = getsockopt(fSockfd, IPPROTO_IP, IP_TOS, &tos, &len);
 -         
 -         tos = 46 * 4;       // see <netinet/in.h> 
 -         res = setsockopt(fSockfd, IPPROTO_IP, IP_TOS, &tos, sizeof(tos));
 - 
 -         return fSockfd;
 -     }
 - 
 -     bool JackNetUnixSocket::IsLocal(char* ip)
 -     {
 -         if (strcmp(ip, "127.0.0.1") == 0) {
 -             return true;
 -         }
 - 
 -         char host_name[32];
 -         gethostname(host_name, sizeof(host_name));
 - 
 -         struct hostent* host = gethostbyname(host_name);
 -         if (host) {
 -             for (int i = 0; host->h_addr_list[i] != 0; ++i) {
 -                 struct in_addr addr;
 -                 memcpy(&addr, host->h_addr_list[i], sizeof(struct in_addr));
 -                 if (strcmp(inet_ntoa(addr), ip) == 0) {
 -                     return true;
 -                 }
 -             }
 -             return false;
 -         } else {
 -             return false;
 -         }
 -     }
 - 
 -     int JackNetUnixSocket::Bind()
 -     {
 -         return ::bind(fSockfd, reinterpret_cast<socket_address_t*>(&fRecvAddr), sizeof(socket_address_t));
 -     }
 - 
 -     int JackNetUnixSocket::BindWith(const char* ip)
 -     {
 -         int addr_conv = inet_aton(ip, &fRecvAddr.sin_addr);
 -         if (addr_conv < 0) {
 -             return addr_conv;
 -         }
 -         return Bind();
 -     }
 - 
 -     int JackNetUnixSocket::BindWith(int port)
 -     {
 -         fRecvAddr.sin_port = htons(port);
 -         return Bind();
 -     }
 - 
 -     int JackNetUnixSocket::Connect()
 -     {
 -         return connect(fSockfd, reinterpret_cast<socket_address_t*>(&fSendAddr), sizeof(socket_address_t));
 -     }
 - 
 -     int JackNetUnixSocket::ConnectTo(const char* ip)
 -     {
 -         int addr_conv = inet_aton(ip, &fSendAddr.sin_addr);
 -         if (addr_conv < 0) {
 -             return addr_conv;
 -         }
 -         return Connect();
 -     }
 - 
 -     void JackNetUnixSocket::Close()
 -     {
 -         if (fSockfd) {
 -             close(fSockfd);
 -         }
 -         fSockfd = 0;
 -     }
 - 
 -     void JackNetUnixSocket::Reset()
 -     {
 -         fSendAddr.sin_family = AF_INET;
 -         fSendAddr.sin_port = htons(fPort);
 -         fSendAddr.sin_addr.s_addr = htonl(INADDR_ANY);
 -         memset(&fSendAddr.sin_zero, 0, 8);
 -         fRecvAddr.sin_family = AF_INET;
 -         fRecvAddr.sin_port = htons(fPort);
 -         fRecvAddr.sin_addr.s_addr = htonl(INADDR_ANY);
 -         memset(&fRecvAddr.sin_zero, 0, 8);
 -     }
 - 
 -     bool JackNetUnixSocket::IsSocket()
 -     {
 -         return(fSockfd) ? true : false;
 -     }
 - 
 -     //IP/PORT***********************************************************************************************************
 -     void JackNetUnixSocket::SetPort(int port)
 -     {
 -         fPort = port;
 -         fSendAddr.sin_port = htons(port);
 -         fRecvAddr.sin_port = htons(port);
 -     }
 - 
 -     int JackNetUnixSocket::GetPort()
 -     {
 -         return fPort;
 -     }
 - 
 -     //address***********************************************************************************************************
 -     int JackNetUnixSocket::SetAddress(const char* ip, int port)
 -     {
 -         int addr_conv = inet_aton(ip, &fSendAddr.sin_addr);
 -         if (addr_conv < 0) {
 -             return addr_conv;
 -         }
 -         fSendAddr.sin_port = htons(port);
 -         return 0;
 -     }
 - 
 -     char* JackNetUnixSocket::GetSendIP()
 -     {
 -         return inet_ntoa(fSendAddr.sin_addr);
 -     }
 - 
 -     char* JackNetUnixSocket::GetRecvIP()
 -     {
 -         return inet_ntoa(fRecvAddr.sin_addr);
 -     }
 - 
 -     //utility************************************************************************************************************
 -     int JackNetUnixSocket::GetName(char* name)
 -     {
 -         return gethostname(name, 255);
 -     }
 - 
 -     int JackNetUnixSocket::JoinMCastGroup(const char* ip)
 -     {
 -         struct ip_mreq multicast_req;
 -         inet_aton(ip, &multicast_req.imr_multiaddr);
 -         multicast_req.imr_interface.s_addr = htonl(INADDR_ANY);
 -         return SetOption(IPPROTO_IP, IP_ADD_MEMBERSHIP, &multicast_req, sizeof(multicast_req));
 -     }
 - 
 -     //options************************************************************************************************************
 -     int JackNetUnixSocket::SetOption(int level, int optname, const void* optval, socklen_t optlen)
 -     {
 -         return setsockopt(fSockfd, level, optname, optval, optlen);
 -     }
 - 
 -     int JackNetUnixSocket::GetOption(int level, int optname, void* optval, socklen_t* optlen)
 -     {
 -         return getsockopt(fSockfd, level, optname, optval, optlen);
 -     }
 - 
 -     //timeout************************************************************************************************************
 - 
 - #if defined(__sun__) || defined(sun)
 -     int JackNetUnixSocket::SetTimeOut(int us)
 -     {
 -         int	flags;
 -         fTimeOut = us;
 - 
 -         if ((flags = fcntl(fSockfd, F_GETFL, 0)) < 0) {
 - 		    jack_error("JackNetUnixSocket::SetTimeOut error in fcntl F_GETFL");
 - 		    return -1;
 - 	    }
 - 
 - 	    flags |= O_NONBLOCK;
 - 	    if (fcntl(fSockfd, F_SETFL, flags) < 0) {
 - 		    jack_error("JackNetUnixSocket::SetTimeOut error in fcntl F_SETFL");
 - 		    return 1;
 - 	    }
 - 
 -         return 0;
 -     }
 - 
 -     int JackNetUnixSocket::WaitRead()
 -     {
 -         if (fTimeOut > 0) {
 - 
 -             struct timeval tv;
 - 	        fd_set fdset;
 -             ssize_t	res;
 - 
 -             tv.tv_sec = fTimeOut / 1000000;
 - 	        tv.tv_usec = fTimeOut % 1000000;
 - 
 - 	        FD_ZERO(&fdset);
 - 	        FD_SET(fSockfd, &fdset);
 - 
 - 	        do {
 - 		        res = select(fSockfd + 1, &fdset, NULL, NULL, &tv);
 - 	        } while (res < 0 && errno == EINTR);
 - 
 - 	        if (res < 0) {
 -  		        return res;
 -             } else if (res == 0) {
 -                 errno = ETIMEDOUT;
 - 		        return -1;
 - 	        }
 -         }
 - 
 -         return 0;
 -     }
 - 
 -     int JackNetUnixSocket::WaitWrite()
 -     {
 -         if (fTimeOut > 0) {
 - 
 -             struct timeval tv;
 - 	        fd_set fdset;
 -             ssize_t	res;
 - 
 -             tv.tv_sec = fTimeOut / 1000000;
 -             tv.tv_usec = fTimeOut % 1000000;
 - 
 - 	        FD_ZERO(&fdset);
 - 	        FD_SET(fSockfd, &fdset);
 - 
 - 	        do {
 - 		        res = select(fSockfd + 1, NULL, &fdset, NULL, &tv);
 - 	        } while (res < 0 && errno == EINTR);
 - 
 - 	        if (res < 0) {
 - 		        return res;
 -             } else if (res == 0) {
 -                 errno = ETIMEDOUT;
 - 		        return -1;
 - 	        }
 -         }
 - 
 -         return 0;
 -     }
 - 
 - #else
 -     int JackNetUnixSocket::SetTimeOut(int us)
 -     {
 -         jack_log("JackNetUnixSocket::SetTimeout %d usecs", us);
 -         struct timeval timeout;
 - 
 -         //less than 1 sec
 -         if (us < 1000000) {
 -             timeout.tv_sec = 0;
 -             timeout.tv_usec = us;
 -         } else {
 -         //more than 1 sec
 -             float sec = float(us) / 1000000.f;
 -             timeout.tv_sec = (int)sec;
 -             float usec = (sec - float(timeout.tv_sec)) * 1000000;
 -             timeout.tv_usec =(int)usec;
 -         }
 -         return SetOption(SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout));
 -     }
 - #endif
 - 
 -     //local loop**********************************************************************************************************
 -     int JackNetUnixSocket::SetLocalLoop()
 -     {
 -         char disable = 0;
 -         return SetOption(IPPROTO_IP, IP_MULTICAST_LOOP, &disable, sizeof(disable));
 -     }
 - 
 -     //network operations**************************************************************************************************
 -     int JackNetUnixSocket::SendTo(const void* buffer, size_t nbytes, int flags)
 -     {
 -     #if defined(__sun__) || defined(sun)
 -         if (WaitWrite() < 0) {
 -             return -1;
 -         }
 -     #endif
 -         int res;
 -         if ((res = sendto(fSockfd, buffer, nbytes, flags, reinterpret_cast<socket_address_t*>(&fSendAddr), sizeof(socket_address_t))) < 0) {
 -             jack_error("SendTo fd = %ld err = %s", fSockfd, strerror(errno));
 -         }
 -         return res;
 -     }
 - 
 -     int JackNetUnixSocket::SendTo(const void* buffer, size_t nbytes, int flags, const char* ip)
 -     {
 -         int addr_conv = inet_aton(ip, &fSendAddr.sin_addr);
 -         if (addr_conv < 1) {
 -             return addr_conv;
 -         }
 -         fSendAddr.sin_port = htons(fPort);
 -     #if defined(__sun__) || defined(sun)
 -         if (WaitWrite() < 0) {
 -             return -1;
 -         }
 -     #endif
 -         return SendTo(buffer, nbytes, flags);
 -     }
 - 
 -     int JackNetUnixSocket::Send(const void* buffer, size_t nbytes, int flags)
 -     {
 -     #if defined(__sun__) || defined(sun)
 -         if (WaitWrite() < 0) {
 -             return -1;
 -         }
 -     #endif
 -         int res;
 -         if ((res = send(fSockfd, buffer, nbytes, flags)) < 0) {
 -             jack_error("Send fd = %ld err = %s", fSockfd, strerror(errno));
 -         }
 -         return res;
 -     }
 - 
 -     int JackNetUnixSocket::RecvFrom(void* buffer, size_t nbytes, int flags)
 -     {
 -         socklen_t addr_len = sizeof(socket_address_t);
 -     #if defined(__sun__) || defined(sun)
 -         if (WaitRead() < 0) {
 -             return -1;
 -         }
 -     #endif
 -         int res;
 -         if ((res = recvfrom(fSockfd, buffer, nbytes, flags, reinterpret_cast<socket_address_t*>(&fRecvAddr), &addr_len)) < 0) {
 -             jack_error("RecvFrom fd = %ld err = %s", fSockfd, strerror(errno));
 -         }
 -         return res;        
 -     }
 - 
 -     int JackNetUnixSocket::Recv(void* buffer, size_t nbytes, int flags)
 -     {
 -     #if defined(__sun__) || defined(sun)
 -         if (WaitRead() < 0) {
 -             return -1;
 -         }
 -     #endif
 -         int res;
 -         if ((res = recv(fSockfd, buffer, nbytes, flags)) < 0) {
 -             jack_error("Recv fd = %ld err = %s", fSockfd, strerror(errno));
 -         }
 -         return res;        
 -     }
 - 
 -     int JackNetUnixSocket::CatchHost(void* buffer, size_t nbytes, int flags)
 -     {
 -         socklen_t addr_len = sizeof(socket_address_t);
 -     #if defined(__sun__) || defined(sun)
 -         if (WaitRead() < 0) {
 -             return -1;
 -         }
 -     #endif
 -         int res;
 -         if ((res = recvfrom(fSockfd, buffer, nbytes, flags, reinterpret_cast<socket_address_t*>(&fSendAddr), &addr_len)) < 0) {
 -             jack_log("CatchHost fd = %ld err = %s", fSockfd, strerror(errno));
 -         }
 -         return res;                
 -     }
 - 
 -     net_error_t JackNetUnixSocket::GetError()
 -     {
 -         switch (errno) {
 -             case EAGAIN:
 -             case ETIMEDOUT:
 -                 return NET_NO_DATA;
 - 
 -             case ECONNABORTED:
 -             case ECONNREFUSED:
 -             case ECONNRESET:
 -             case EINVAL:
 -             case EHOSTDOWN:
 -             case EHOSTUNREACH:
 -             case ENETDOWN:
 -             case ENETUNREACH:
 -                 return NET_CONN_ERROR;
 - 
 -             default:
 -                 //return NET_OP_ERROR;
 -                 return NET_CONN_ERROR;
 -         }
 -     }
 -         
 -     void JackNetUnixSocket::PrintError()
 -     {
 -         switch (errno) {
 -                 
 -             case EAGAIN:
 -                 jack_error("JackNetUnixSocket : EAGAIN");
 -                 break;
 -             case ETIMEDOUT:
 -                 jack_error("JackNetUnixSocket : ETIMEDOUT");
 -                 break;
 -             case ECONNABORTED:
 -                 jack_error("JackNetUnixSocket : ECONNABORTED");
 -                 break;
 -             case ECONNREFUSED:
 -                 jack_error("JackNetUnixSocket : ECONNREFUSED");
 -                 break;
 -             case ECONNRESET:
 -                 jack_error("JackNetUnixSocket : ECONNRESET");
 -                 break;
 -             case EINVAL:
 -                 jack_error("JackNetUnixSocket : EINVAL");
 -                 break;
 -             case EHOSTDOWN:
 -                 jack_error("JackNetUnixSocket : EHOSTDOWN");
 -                 break;
 -             case EHOSTUNREACH:
 -                 jack_error("JackNetUnixSocket : EHOSTUNREACH");
 -                 break;
 -             case ENETDOWN:
 -                 jack_error("JackNetUnixSocket : ENETDOWN");
 -                 break;
 -             case ENETUNREACH:
 -                 jack_error("JackNetUnixSocket : ENETUNREACH");
 -                 break;
 -             default:
 -                 jack_error("JackNetUnixSocket : %d", errno);
 -                 break;
 -         }
 -     }    
 - }
 
 
  |