aboutsummaryrefslogtreecommitdiffstats
path: root/src/TcpSocket.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/TcpSocket.cpp')
-rw-r--r--src/TcpSocket.cpp366
1 files changed, 366 insertions, 0 deletions
diff --git a/src/TcpSocket.cpp b/src/TcpSocket.cpp
new file mode 100644
index 0000000..723d06b
--- /dev/null
+++ b/src/TcpSocket.cpp
@@ -0,0 +1,366 @@
+/*
+ Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Her Majesty the Queen in
+ Right of Canada (Communications Research Center Canada)
+ */
+/*
+ This file is part of CRC-DabMux.
+
+ CRC-DabMux 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 3 of the
+ License, or (at your option) any later version.
+
+ CRC-DabMux 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 CRC-DabMux. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "TcpSocket.h"
+#include <iostream>
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <signal.h>
+
+#ifdef _WIN32
+#else
+# include <unistd.h>
+#endif
+
+#ifdef TRACE_ON
+# ifndef TRACE_CLASS
+# define TRACE_CLASS(class, func) cout <<"-" <<(class) <<"\t(" <<this <<")::" <<(func) <<endl
+# define TRACE_STATIC(class, func) cout <<"-" <<(class) <<"\t(static)::" <<(func) <<endl
+# endif
+#else
+# ifndef TRACE_CLASS
+# define TRACE_CLASS(class, func)
+# define TRACE_STATIC(class, func)
+# endif
+#endif
+
+
+/// Must be call once before doing any operation on sockets
+int TcpSocket::init()
+{
+#ifdef _WIN32
+ WSADATA wsaData;
+ WORD wVersionRequested = wVersionRequested = MAKEWORD( 2, 2 );
+
+ int res = WSAStartup( wVersionRequested, &wsaData );
+ if (res) {
+ setInetError("Can't initialize winsock");
+ return -1;
+ }
+#endif
+ return 0;
+}
+
+
+/// Must be call once before leaving application
+int TcpSocket::clean()
+{
+#ifdef _WIN32
+ int res = WSACleanup();
+ if (res) {
+ setInetError("Can't initialize winsock");
+ return -1;
+ }
+#endif
+ return 0;
+}
+
+
+/**
+ * Two step constructor. Create must be called prior to use this
+ * socket.
+ */
+TcpSocket::TcpSocket() :
+ listenSocket(INVALID_SOCKET)
+{
+ TRACE_CLASS("TcpSocket", "TcpSocket()");
+}
+
+
+/**
+ * One step constructor.
+ * @param port The port number on which the socket will be bind
+ * @param name The IP address on which the socket will be bind.
+ * It is used to bind the socket on a specific interface if
+ * the computer have many NICs.
+ */
+TcpSocket::TcpSocket(int port, char *name) :
+ listenSocket(INVALID_SOCKET)
+{
+ TRACE_CLASS("TcpSocket", "TcpSocket(int, char*)");
+ create(port, name);
+}
+
+
+/**
+ * Close the underlying socket.
+ * @return 0 if ok
+ * -1 if error
+ */
+int TcpSocket::close()
+{
+ TRACE_CLASS("TcpSocket", "close()");
+ if (listenSocket != INVALID_SOCKET) {
+ int res = closesocket(listenSocket);
+ if (res != 0) {
+ setInetError("Can't close socket");
+ return -1;
+ }
+ listenSocket = INVALID_SOCKET;
+ }
+ return 0;
+}
+
+
+/**
+ * Two step initializer. This function must be called after the constructor
+ * without argument as been called.
+ * @param port The port number on which the socket will be bind
+ * @param name The IP address on which the socket will be bind.
+ * It is used to bind the socket on a specific interface if
+ * the computer have many NICs.
+ * @return 0 if ok
+ * -1 if error
+ */
+int TcpSocket::create(int port, char *name)
+{
+ TRACE_CLASS("TcpSocket", "create(int, char*)");
+ if (listenSocket != INVALID_SOCKET)
+ closesocket(listenSocket);
+ address.setAddress(name);
+ address.setPort(port);
+ if ((listenSocket = socket(PF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) {
+ setInetError("Can't create socket");
+ return -1;
+ }
+ reuseopt_t reuse = 1;
+ if (setsockopt(listenSocket, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse))
+ == SOCKET_ERROR) {
+ setInetError("Can't reuse address");
+ return -1;
+ }
+ if (bind(listenSocket, address.getAddress(), sizeof(sockaddr_in)) == SOCKET_ERROR) {
+ setInetError("Can't bind socket");
+ closesocket(listenSocket);
+ listenSocket = INVALID_SOCKET;
+ return -1;
+ }
+ return 0;
+}
+
+
+/// Destructor
+TcpSocket::~TcpSocket() {
+ TRACE_CLASS("TcpSocket", "~TcpSocket()");
+ close();
+}
+
+
+/**
+ * Receive an telnet packet, i.e a TCP stream ending with carriage return.
+ * @param data The buffer that will receive data.
+ * @param size The buffer size.
+ * @return > 0 if ok, -1 (SOCKET_ERROR) if error
+ */
+int TcpSocket::telnetRead(void* data, int size)
+{
+ TRACE_CLASS("TcpSocket", "read(void*, size)");
+ int ret;
+
+ printf("selectCall\n");
+
+ printf("readread 1\n");
+ char *line=GetLine(listenSocket);
+ ret=strlen(line);
+ printf("readread 2\n");
+ if (ret <= size)
+ {
+ strcpy((char*)data, line);
+ }
+ else
+ {
+// size_t n = size;
+ strcpy((char*)data, line);
+ ret = size;
+ }
+ printf("TELNET READ returned %d\n", ret);
+ return ret;
+}
+
+/**
+ * Receive a TCP stream.
+ * @param data The buffer that will receive data.
+ * @param size The buffer size.
+ * @return > 0 if ok, -1 (SOCKET_ERROR) if error
+ */
+int TcpSocket::read(void* data, int size)
+{
+ TRACE_CLASS("TcpSocket", "read(void*, size)");
+
+ int ret = recv(listenSocket, (char*)data, size, 0);
+ if (ret == SOCKET_ERROR) {
+ setInetError("Can't receive TCP packet");
+ return -1;
+ }
+ return ret;
+}
+
+
+#define MAX 512
+char* TcpSocket::GetLine(int fd)
+{
+ static char line[MAX];
+ static char netread[MAX] = "";
+ int n, len;
+ char *p;
+
+ len = strlen(netread);
+
+ /* look for \r\n in netread buffer */
+ p = strstr(netread, "\r\n");
+ if (p == NULL) {
+ /* fill buff - no \r\n found */
+ //n = ::read(fd, (void*)(netread+len), (size_t)(MAX-len));
+ n = recv(fd, (netread+len), MAX-len, 0);
+ if (n == SOCKET_ERROR) {
+ setInetError("Can't receive TCP packet");
+ return NULL;
+ }
+ len += n;
+ netread[len] = '\0';
+ if (n>0)
+ return GetLine(fd);
+ }
+ if (p!=NULL)
+ {
+ *p = '\0';
+ strcpy(line, netread);
+ /* copy rest of buf down */
+ memmove(netread, p+2, strlen(p+2)+1);
+ }
+ return line;
+}
+
+
+/**
+ * Send an TCP packet.
+ * @param data The buffer taht will be sent.
+ * @param size Number of bytes to send.
+ * return 0 if ok, -1 if error
+ */
+int TcpSocket::write(const void* data, int size)
+{
+#ifdef DUMP
+ TRACE_CLASS("TcpSocket", "write(const void*, int)");
+#endif
+
+ // ignore BROKENPIPE signal (we handle it instead)
+// void* old_sigpipe = signal ( SIGPIPE, SIG_IGN );
+ // try to send data
+ int ret = send(listenSocket, (char*)data, size, 0 /*MSG_NOSIGNAL*/ );
+ // restore the BROKENPIPE handling
+// signal ( SIGPIPE, (__sighandler_t)old_sigpipe );
+ if (ret == SOCKET_ERROR) {
+ setInetError("Can't send TCP packet");
+ return -1;
+ }
+ return ret;
+}
+
+
+int TcpSocket::setDestination(InetAddress &addr)
+{
+ address = addr;
+ int ret = connect(listenSocket, addr.getAddress(), sizeof(*addr.getAddress()));
+ // A etre verifier: code de retour differend entre Linux et Windows
+ return ret;
+}
+
+
+void TcpSocket::setSocket(SOCKET socket, InetAddress &addr)
+{
+ if (listenSocket != INVALID_SOCKET)
+ closesocket(listenSocket);
+ listenSocket = socket;
+ address = addr;
+}
+
+
+InetAddress TcpSocket::getAddress()
+{
+ return address;
+}
+
+
+int TcpSocket::PeekCount()
+{
+ int count;
+ char tempBuffer[3];
+ int size=3;
+
+ count = recv(listenSocket, tempBuffer, size, MSG_PEEK);
+ if (count == -1)
+ {
+ printf("ERROR WHEN PEEKING SOCKET\n");
+ }
+ return count;
+}
+
+/*
+WSAEINTR
+WSAEBADF
+WSAEACCES
+WSAEFAULT
+WSAEINVAL
+WSAEMFILE
+WSAEWOULDBLOCK
+WSAEINPROGRESS
+WSAEALREADY
+WSAENOTSOCK
+WSAEDESTADDRREQ
+WSAEMSGSIZE
+WSAEPROTOTYPE
+WSAENOPROTOOPT
+WSAEPROTONOSUPPORT
+WSAESOCKTNOSUPPORT
+WSAEOPNOTSUPP
+WSAEPFNOSUPPORT
+WSAEAFNOSUPPORT
+WSAEADDRINUSE
+WSAEADDRNOTAVAIL
+WSAENETDOWN
+WSAENETUNREACH
+WSAENETRESET
+WSAECONNABORTED
+WSAECONNRESET
+WSAENOBUFS
+WSAEISCONN
+WSAENOTCONN
+WSAESHUTDOWN
+WSAETOOMANYREFS
+WSAETIMEDOUT
+WSAECONNREFUSED
+WSAELOOP
+WSAENAMETOOLONG
+WSAEHOSTDOWN
+WSAEHOSTUNREACH
+WSAENOTEMPTY
+WSAEPROCLIM
+WSAEUSERS
+WSAEDQUOT
+WSAESTALE
+WSAEREMOTE
+WSAEDISCON
+WSASYSNOTREADY
+WSAVERNOTSUPPORTED
+WSANOTINITIALISED
+*/