/* Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Her Majesty the Queen in Right of Canada (Communications Research Center Canada) Copyright (C) 2013 Matthias P. Braendli http://mpb.li TCP output */ /* This file is part of ODR-DabMux. ODR-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. ODR-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 ODR-DabMux. If not, see . */ #include #include #include #include #include "dabOutput.h" #include "TcpServer.h" #ifdef _WIN32 # include # ifdef __MINGW32__ # define FS_DECLARE_CFG_ARRAYS # include # endif # include #else # include # include # ifndef O_BINARY # define O_BINARY 0 # endif // O_BINARY #endif void* tcpThread(void* param) { TcpSocket* client; DabOutputTcp* tcp = (DabOutputTcp*)param; while ((client = tcp->server->accept()) != NULL) { etiLog.log(info, "TCP server got a new client.\n"); if (tcp->client != NULL) { delete tcp->client; } tcp->client = client; } etiLog.log(error, "TCP thread can't accept new client (%s)\n", inetErrDesc, inetErrMsg); return NULL; } int DabOutputTcp::Open(const char* name) { char* hostport = strdup(name); // the name is actually an tuple host:port char* address; long port; address = strchr((char*)hostport, ':'); if (address == NULL) { etiLog.log(error, "\"%s\" is an invalid format for tcp address: " "should be [address]:port - > aborting\n", hostport); goto tcp_open_fail; } // terminate string hostport after the host, and advance address to the port number *(address++) = 0; port = strtol(address, (char **)NULL, 10); if ((port == LONG_MIN) || (port == LONG_MAX)) { etiLog.log(error, "can't convert port number in tcp address %s\n", address); goto tcp_open_fail; } if (port == 0) { etiLog.log(error, "can't use port number 0 in tcp address\n"); goto tcp_open_fail; } address = hostport; if (strlen(address) > 0) { if (this->server->create(port, address) == -1) { etiLog.log(error, "Can't create Tcp server on %s:%i " "(%s: %s) -> aborting\n", address, port, inetErrDesc, inetErrMsg); goto tcp_open_fail; } } else { if (this->server->create(port) == -1) { etiLog.log(error, "Can't create Tcp server on :%i " "(%s: %s) -> aborting\n", port, inetErrDesc, inetErrMsg); goto tcp_open_fail; } } //sprintf(name, "%s:%i", this->packet_->getAddress().getHostAddress(), // this->packet_->getAddress().getPort()); if (this->server->listen() == -1) { etiLog.log(error, "Can't listen on Tcp socket (%s: %s)\n", inetErrDesc, inetErrMsg); goto tcp_open_fail; } #ifdef _WIN32 this->thread_ = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)tcpThread, this, 0, NULL); if (this->thread_ == NULL) { fprintf(stderr, "Can't create TCP child"); goto tcp_open_fail; } #else if (pthread_create(&this->thread_, NULL, tcpThread, this)) { perror("Can't create TCP child"); goto tcp_open_fail; } #endif return 0; tcp_open_fail: free(hostport); return -1; } int DabOutputTcp::Write(void* buffer, int size) { if (this->client != NULL) { if (this->client->write(&size, 2) == 2) { if (this->client->write(buffer, size) != size) { return size; } } else { etiLog.log(info, "TCP server client disconnected.\n"); delete this->client; this->client = NULL; } } return size; } int DabOutputTcp::Close() { this->server->close(); if( this->client != NULL ) this->client->close(); #ifdef WIN32 DWORD status; for (int i = 0; i < 5; ++i) { if (GetExitCodeThread(this->thread_, &status)) { break; } Sleep(100); } TerminateThread(this->thread_, 1); #else pthread_kill(this->thread_, SIGPIPE); #endif return 0; }