summaryrefslogtreecommitdiff
path: root/tool_socket.c
diff options
context:
space:
mode:
Diffstat (limited to 'tool_socket.c')
-rw-r--r--tool_socket.c197
1 files changed, 197 insertions, 0 deletions
diff --git a/tool_socket.c b/tool_socket.c
new file mode 100644
index 0000000..ef20561
--- /dev/null
+++ b/tool_socket.c
@@ -0,0 +1,197 @@
+#include "tool_socket.h"
+
+#include <vdr/tools.h>
+
+#include <string.h>
+#include <arpa/inet.h>
+#include <unistd.h>
+#include <errno.h>
+#include <fcntl.h>
+
+#define UDP_TX_BUF_SIZE (188*348)
+//#define TCP_TX_BUF_SIZE (1024 * 60)
+
+cTBSocket::cTBSocket(int Type) {
+ memset(&m_LocalAddr, 0, sizeof(m_LocalAddr));
+ memset(&m_RemoteAddr, 0, sizeof(m_RemoteAddr));
+ m_Type = Type;
+}
+
+cTBSocket::~cTBSocket() {
+ if (IsOpen()) Close();
+}
+
+bool cTBSocket::OpenUDP(const std::string &Host, unsigned int Port) {
+ int socket;
+ struct sockaddr_in my_addr;
+
+ if (IsOpen()) Close();
+
+ if ((socket = ::socket(AF_INET, m_Type, 0)) == -1)
+ return false;
+
+ m_RemoteAddr.sin_family = AF_INET;
+ m_RemoteAddr.sin_port = htons(Port);
+ m_RemoteAddr.sin_addr.s_addr = inet_addr(Host.c_str());
+
+ my_addr.sin_family = AF_INET;
+ my_addr.sin_port = htons(Port);
+ my_addr.sin_addr.s_addr = htonl(INADDR_ANY);
+
+ /* limit the tx buf size to limit latency */
+#ifdef UDP_TX_BUF_SIZE
+ int tmp = UDP_TX_BUF_SIZE;
+ if (setsockopt(socket, SOL_SOCKET, SO_SNDBUF, (char*)&tmp, sizeof(tmp)) < 0)
+ goto closefd;
+#endif
+
+/* tmp = 1;
+ if (setsockopt(socket, SOL_SOCKET, SO_REUSEADDR, (char*)&tmp, sizeof(tmp)) < 0)
+ goto closefd;*/
+
+ /* the bind is needed to give a port to the socket now */
+/* if (bind(socket,(struct sockaddr *)&my_addr, sizeof(my_addr)) < 0)
+ goto closefd;*/
+
+ if (!cTBSource::Open(socket))
+ goto closefd; // return false;
+
+ return true;
+
+closefd:
+ ::close(socket);
+ return false;
+}
+
+bool cTBSocket::Connect(const std::string &Host, unsigned int Port) {
+ socklen_t len;
+ int socket;
+
+ if (IsOpen()) Close();
+
+ if ((socket = ::socket(PF_INET, m_Type, IPPROTO_IP)) == -1)
+ return false;
+
+ m_LocalAddr.sin_family = AF_INET;
+ m_LocalAddr.sin_port = 0;
+ m_LocalAddr.sin_addr.s_addr = INADDR_ANY;
+ if (::bind(socket, (struct sockaddr*)&m_LocalAddr, sizeof(m_LocalAddr))
+ == -1)
+ goto closefd; //return false;
+
+ m_RemoteAddr.sin_family = AF_INET;
+ m_RemoteAddr.sin_port = htons(Port);
+ m_RemoteAddr.sin_addr.s_addr = inet_addr(Host.c_str());
+ if (::connect(socket, (struct sockaddr*)&m_RemoteAddr,
+ sizeof(m_RemoteAddr)) == -1)
+ goto closefd; //return false;
+
+ len = sizeof(struct sockaddr_in);
+ if (::getpeername(socket, (struct sockaddr*)&m_RemoteAddr, &len) == -1)
+ goto closefd; //return false;
+
+ len = sizeof(struct sockaddr_in);
+ if (::getsockname(socket, (struct sockaddr*)&m_LocalAddr, &len) == -1)
+ goto closefd; //return false;
+
+ return cTBSource::Open(socket);
+
+closefd:
+ ::close(socket);
+ return false;
+}
+
+bool cTBSocket::Listen(const std::string &Ip, unsigned int Port, int BackLog) {
+ int val;
+ socklen_t len;
+ int socket;
+
+ if (IsOpen()) Close();
+
+ if ((socket = ::socket(PF_INET, m_Type, IPPROTO_IP)) == -1)
+ return false;
+
+ /* limit the tx buf size to limit latency */
+#ifdef TCP_TX_BUF_SIZE
+ int tmp = TCP_TX_BUF_SIZE;
+ if (setsockopt(socket, SOL_SOCKET, SO_SNDBUF, (char*)&tmp, sizeof(tmp)) < 0)
+ goto closefd;
+#endif
+
+ val = 1;
+ if (::setsockopt(socket, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)) == -1)
+ goto closefd; //return false;
+
+ m_LocalAddr.sin_family = AF_INET;
+ m_LocalAddr.sin_port = htons(Port);
+ m_LocalAddr.sin_addr.s_addr = inet_addr(Ip.c_str());
+ if (::bind(socket, (struct sockaddr*)&m_LocalAddr, sizeof(m_LocalAddr))
+ == -1)
+ goto closefd; //return false;
+
+ len = sizeof(struct sockaddr_in);
+ if (::getsockname(socket, (struct sockaddr*)&m_LocalAddr, &len) == -1)
+ goto closefd; //return false;
+
+ if (m_Type == SOCK_STREAM && ::listen(socket, BackLog) == -1)
+ goto closefd; //return false;
+
+ if (!cTBSource::Open(socket))
+ goto closefd; // return false;
+
+ return true;
+
+closefd:
+ ::close(socket);
+ return false;
+}
+
+bool cTBSocket::Accept(const cTBSocket &Listener) {
+ socklen_t addrlen;
+ int socket;
+
+ if (IsOpen()) Close();
+
+ addrlen = sizeof(struct sockaddr_in);
+ if ((socket = ::accept(Listener, (struct sockaddr*)&m_RemoteAddr,
+ &addrlen)) == -1)
+ return false;
+
+ addrlen = sizeof(struct sockaddr_in);
+ if (::getsockname(socket, (struct sockaddr*)&m_LocalAddr, &addrlen) == -1)
+ return false;
+
+ if (!cTBSource::Open(socket))
+ return false;
+
+ return true;
+}
+
+RETURNS(cTBSocket, cTBSocket::Accept(void) const, ret)
+ ret.Accept(*this);
+RETURN(ret)
+
+bool cTBSocket::Close(void) {
+ bool ret = true;
+
+ if (!IsOpen())
+ ERRNUL(EBADF);
+
+ if (::close(*this) == -1)
+ ret = false;
+
+ if (!cTBSource::Close())
+ ret = false;
+
+ memset(&m_LocalAddr, 0, sizeof(m_LocalAddr));
+ memset(&m_RemoteAddr, 0, sizeof(m_RemoteAddr));
+
+ return ret;
+}
+
+bool cTBSocket::Shutdown(int how) {
+ if (!IsOpen())
+ ERRNUL(EBADF);
+
+ return ::shutdown(*this, how) != -1;
+}