2
// Copyright (C) 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
4
// This program is free software; you can redistribute it and/or modify
5
// it under the terms of the GNU General Public License as published by
6
// the Free Software Foundation; either version 3 of the License, or
7
// (at your option) any later version.
9
// This program is distributed in the hope that it will be useful,
10
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
// GNU General Public License for more details.
14
// You should have received a copy of the GNU General Public License
15
// along with this program; if not, write to the Free Software
16
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20
#include "gnashconfig.h"
23
#include <boost/thread/mutex.hpp>
30
#include <sys/types.h>
35
#if defined(HAVE_WINSOCK_H) && !defined(__OS2__)
36
# include <winsock2.h>
38
# include <sys/stat.h>
40
# include <ws2tcpip.h>
42
# include <sys/time.h>
44
# include <sys/select.h>
45
# include <netinet/in.h>
46
# include <arpa/inet.h>
47
# include <sys/socket.h>
50
# include <sys/param.h>
51
# include <sys/select.h>
56
#ifndef MAXHOSTNAMELEN
57
#define MAXHOSTNAMELEN 256
64
static const char *DEFAULTPROTO = "tcp";
65
static const short DEFAULTPORT = RTMP_PORT;
68
#define INADDR_NONE 0xffffffff
81
// GNASH_REPORT_FUNCTION;
82
#if defined(HAVE_WINSOCK_H) && !defined(__OS2__)
83
WORD wVersionRequested;
85
wVersionRequested = MAKEWORD(1, 1); // Windows Sockets 1.1
86
if (WSAStartup( wVersionRequested, &wsaData ) != 0) {
87
log_error(_("Could not find a usable WinSock DLL"));
96
// GNASH_REPORT_FUNCTION;
97
#if defined(HAVE_WINSOCK_H) && !defined(__OS2__)
104
// Description: Create a tcp/ip network server. This creates a server
105
// that listens for incoming socket connections. This
106
// supports IP aliasing on the host, and will sequntially
107
// look for IP address to bind this port to.
109
Network::createServer(void)
111
// GNASH_REPORT_FUNCTION;
113
return createServer(DEFAULTPORT);
116
// FIXME: Should also support IPv6 (AF_INET6)
118
Network::createServer(short port)
120
// GNASH_REPORT_FUNCTION;
122
struct protoent *ppe;
123
struct sockaddr_in sock_in;
130
log_error(_("Can't connect to privileged port #%d"), port);
135
if (_listenfd >= 2) {
136
log_debug("already connected to port %hd", port);
140
const struct hostent *host = gethostbyname("localhost");
141
struct in_addr *thisaddr = reinterpret_cast<struct in_addr *>(host->h_addr_list[0]);
142
_ipaddr = thisaddr->s_addr;
143
memset(&sock_in, 0, sizeof(sock_in));
146
// Accept incoming connections only on our IP number
147
sock_in.sin_addr.s_addr = thisaddr->s_addr;
149
// Accept incoming connections on any IP number
150
sock_in.sin_addr.s_addr = INADDR_ANY;
153
_ipaddr = sock_in.sin_addr.s_addr;
154
sock_in.sin_family = AF_INET;
155
sock_in.sin_port = htons(port);
157
if ((ppe = getprotobyname(DEFAULTPROTO)) == 0) {
158
log_error(_("unable to get protocol entry for %s"),
164
if ( strcmp(DEFAULTPROTO, "udp") == 0) {
170
// Get a file descriptor for this socket connection
171
_listenfd = socket(PF_INET, type, ppe->p_proto);
173
// error, wasn't able to create a socket
175
log_error(_("unable to create socket: %s"), strerror(errno));
180
if (setsockopt(_listenfd, SOL_SOCKET, SO_REUSEADDR,
181
(char *)&on, sizeof(on)) < 0) {
182
log_error(_("setsockopt SO_REUSEADDR failed"));
188
nodeaddr = inet_lnaof(*thisaddr);
189
while (retries < 5) {
190
if (bind(_listenfd, reinterpret_cast<struct sockaddr *>(&sock_in),
191
sizeof(sock_in)) == -1) {
192
log_error(_("unable to bind to port %hd: %s"),
193
port, strerror(errno));
194
// inet_ntoa(sock_in.sin_addr), strerror(errno));
199
// char ascip[INET_ADDRSTRLEN];
200
// inet_ntop(sock_in.sin_family, &_ipaddr, ascip, INET_ADDRSTRLEN);
201
char *ascip = ::inet_ntoa(sock_in.sin_addr);
202
log_debug(_("Server bound to service on %s, port %hd, using fd #%d"),
203
ascip, ntohs(sock_in.sin_port),
207
if (type == SOCK_STREAM && listen(_listenfd, 5) < 0) {
208
log_error(_("unable to listen on port: %hd: %s "),
209
port, strerror(errno));
213
// We have a socket created
220
// Description: Accept a new network connection for the port we have
221
// created a server for.
222
// The default is to block.
224
Network::newConnection(void)
226
// GNASH_REPORT_FUNCTION;
228
return newConnection(true, _listenfd);
232
Network::newConnection(int fd)
234
// GNASH_REPORT_FUNCTION;
236
return newConnection(true, fd);
240
Network::newConnection(bool block)
242
// GNASH_REPORT_FUNCTION;
244
return newConnection(block, _listenfd);
248
Network::newConnection(bool block, int fd)
250
GNASH_REPORT_FUNCTION;
252
struct sockaddr newfsin;
259
alen = sizeof(struct sockaddr_in);
265
log_debug(_("Trying to accept net traffic on fd #%d for port %d"), fd, _port);
269
// We use select to wait for the read file descriptor to be
270
// active, which means there is a client waiting to connect.
272
// also return on any input from stdin
274
// FD_SET(fileno(stdin), &fdset);
278
// Reset the timeout value, since select modifies it on return. To
279
// block, set the timeout to zero.
284
ret = select(fd+1, &fdset, NULL, NULL, NULL);
286
ret = select(fd+1, &fdset, NULL, NULL, &tval);
289
if (FD_ISSET(0, &fdset)) {
291
log_debug(_("There is data at the console for stdin"));
296
// If interupted by a system call, try again
297
if (ret == -1 && errno == EINTR) {
298
log_debug(_("The accept() socket for fd #%d was interupted by a system call"), fd);
302
log_debug(_("The accept() socket for fd #%d never was available for writing"), fd);
308
log_debug(_("The accept() socket for fd #%d timed out waiting to write"), fd);
313
#ifndef HAVE_WINSOCK_H
314
fcntl(_listenfd, F_SETFL, O_NONBLOCK); // Don't let accept() block
316
_sockfd = accept(fd, &newfsin, &alen);
319
log_error(_("unable to accept: %s"), strerror(errno));
324
log_debug(_("Accepting tcp/ip connection on fd #%d for port %d"), _sockfd, _port);
331
/* from sys/socket.h */
332
typedef unsigned short sa_family_t;
335
#define UNIX_PATH_MAX 108
338
sa_family_t sun_family; /* AF_UNIX */
339
char sun_path[UNIX_PATH_MAX]; /* pathname */
344
// Connect to a named pipe
346
Network::connectSocket(const string &sockname)
348
// GNASH_REPORT_FUNCTION;
350
struct sockaddr_un addr;
356
addr.sun_family = AF_UNIX;
357
// socket names must be 108 bytes or less as specifiec in sys/un.h.
358
strncpy(addr.sun_path, sockname.c_str(), 100);
360
_sockfd = ::socket(AF_UNIX, SOCK_STREAM, 0);
363
log_error(_("unable to create socket: %s"), strerror(errno));
369
while (retries-- > 0) {
370
// We use select to wait for the read file descriptor to be
371
// active, which means there is a client waiting to connect.
373
FD_SET(_sockfd, &fdset);
375
// Reset the timeout value, since select modifies it on return. To
376
// block, set the timeout to zero.
380
ret = ::select(_sockfd+1, &fdset, NULL, NULL, &tval);
382
// If interupted by a system call, try again
383
if (ret == -1 && errno == EINTR)
385
log_debug(_("The connect() socket for fd %d was interupted by a system call"),
392
log_debug(_("The connect() socket for fd %d never was available for writing"),
394
#ifdef HAVE_WINSOCK_H
395
::shutdown(_sockfd, 0); // FIXME: was SHUT_BOTH
397
::shutdown(_sockfd, SHUT_RDWR);
403
log_error(_("The connect() socket for fd %d timed out waiting to write"),
409
ret = ::connect(_sockfd, reinterpret_cast<struct sockaddr *>(&addr), sizeof(addr));
411
log_debug(_("\tsocket name %s for fd %d"), sockname, _sockfd);
417
log_error(_("The connect() socket for fd %d never was available for writing"),
427
#ifndef HAVE_WINSOCK_H
428
fcntl(_sockfd, F_SETFL, O_NONBLOCK);
436
// Create a client connection to a tcp/ip based service
438
Network::createClient(void)
440
// GNASH_REPORT_FUNCTION;
442
return createClient("localhost", RTMP_PORT);
445
Network::createClient(short /* port */)
447
// GNASH_REPORT_FUNCTION;
453
Network::createClient(const string &hostname)
455
// GNASH_REPORT_FUNCTION;
457
return createClient(hostname, RTMP_PORT);
461
Network::createClient(const string &hostname, short port)
463
GNASH_REPORT_FUNCTION;
465
struct sockaddr_in sock_in;
470
char thishostname[MAXHOSTNAMELEN];
471
struct protoent *proto;
473
assert( ! connected() );
476
log_error(_("Can't connect to privileged port %hd"), port);
482
log_debug(_("%s: to host %s at port %d"), __FUNCTION__, hostname, port);
484
memset(&sock_in, 0, sizeof(struct sockaddr_in));
485
memset(&thishostname, 0, MAXHOSTNAMELEN);
486
if (hostname.size() == 0) {
487
if (gethostname(thishostname, MAXHOSTNAMELEN) == 0) {
488
log_debug(_("The hostname for this machine is %s"), thishostname);
490
log_debug(_("Couldn't get the hostname for this machine"));
494
const struct hostent *hent = ::gethostbyname(hostname.c_str());
496
::memcpy(&sock_in.sin_addr, hent->h_addr, hent->h_length);
498
sock_in.sin_family = AF_INET;
499
sock_in.sin_port = ntohs(static_cast<short>(port));
502
char ascip[INET_ADDRSTRLEN];
503
inet_ntop(sock_in.sin_family, &sock_in.sin_addr.s_addr, ascip, INET_ADDRSTRLEN);
504
log_debug(_("The IP address for this client socket is %s"), ascip);
507
proto = ::getprotobyname("TCP");
509
_sockfd = ::socket(PF_INET, SOCK_STREAM, proto->p_proto);
512
log_error(_("unable to create socket: %s"), strerror(errno));
518
while (retries-- > 0) {
519
// We use select to wait for the read file descriptor to be
520
// active, which means there is a client waiting to connect.
522
FD_SET(_sockfd, &fdset);
524
// Reset the timeout value, since select modifies it on return. To
525
// block, set the timeout to zero.
529
ret = ::select(_sockfd+1, &fdset, NULL, NULL, &tval);
531
// If interupted by a system call, try again
532
if (ret == -1 && errno == EINTR)
534
log_debug(_("The connect() socket for fd %d was interupted by a system call"),
541
log_debug(_("The connect() socket for fd %d never was available for writing"),
543
#ifdef HAVE_WINSOCK_H
544
::shutdown(_sockfd, 0); // FIXME: was SHUT_BOTH
546
::shutdown(_sockfd, SHUT_RDWR);
552
log_error(_("The connect() socket for fd %d timed out waiting to write"),
558
ret = ::connect(_sockfd, reinterpret_cast<struct sockaddr *>(&sock_in), sizeof(sock_in));
560
char *ascip = ::inet_ntoa(sock_in.sin_addr);
561
// char ascip[INET_ADDRSTRLEN];
562
// inet_ntop(sock_in.sin_family, &sock_in.sin_addr.s_addr, ascip, INET_ADDRSTRLEN);
563
log_debug(_("\tport %d at IP %s for fd %d"), port,
570
log_error(_("The connect() socket for fd %d never was available for writing"),
581
printf("\tConnected at port %d on IP %s for fd #%d", port,
582
::inet_ntoa(sock_in.sin_addr), _sockfd);
584
#ifndef HAVE_WINSOCK_H
585
fcntl(_sockfd, F_SETFL, O_NONBLOCK);
597
GNASH_REPORT_FUNCTION;
599
if ((_sockfd > 0) && (_connected)) {
609
Network::closeNet(int sockfd)
611
GNASH_REPORT_FUNCTION;
615
// If we can't close the socket, other processes must be
616
// locked on it, so we wait a second, and try again. After a
617
// few tries, we give up, cause there must be something
624
while (retries < 3) {
626
// Shutdown the socket connection
628
if (shutdown(sockfd, SHUT_RDWR) < 0) {
629
if (errno != ENOTCONN) {
630
cerr << "WARNING: Unable to shutdown socket for fd #"
631
<< sockfd << strerror(errno) << endl;
633
cerr << "The socket using fd #" << sockfd
634
<< " has been shut down successfully." << endl;
639
if (::close(sockfd) < 0) {
640
// If we have a bad file descriptor, it's because
641
// this got closed already, usually by another
642
// thread being paranoid.
643
if (errno != EBADF) {
644
log_error(_("Unable to close the socket for fd #%d: %s"),
645
sockfd, strerror(errno));
647
#ifndef HAVE_WINSOCK_H
652
log_debug(_("Closed the socket on fd #%d for port %d"), sockfd, _port);
659
// Description: Close an open socket connection.
661
Network::closeConnection(void)
663
// GNASH_REPORT_FUNCTION;
665
closeConnection(_sockfd);
667
closeConnection(_listenfd);
675
Network::closeConnection(int fd)
677
GNASH_REPORT_FUNCTION;
681
log_debug("%s: Closed fd #%d", __FUNCTION__, fd);
691
// GNASH_REPORT_FUNCTION;
693
amf::Buffer *buffer = new amf::Buffer;
694
int nbytes = readNet(buffer);
696
buffer->resize(nbytes);
703
// Read from the connection
705
Network::readNet(amf::Buffer *buffer)
707
// GNASH_REPORT_FUNCTION;
708
return readNet(_sockfd, buffer->reference(), buffer->size(), _timeout);
712
Network::readNet(amf::Buffer *buffer, int timeout)
714
// GNASH_REPORT_FUNCTION;
715
return readNet(_sockfd, buffer->reference(), buffer->size(), timeout);
719
Network::readNet(byte_t *buffer, int nbytes)
721
// GNASH_REPORT_FUNCTION;
722
return readNet(_sockfd, buffer, nbytes, _timeout);
726
Network::readNet(byte_t *buffer, int nbytes, int timeout)
728
// GNASH_REPORT_FUNCTION;
729
return readNet(_sockfd, buffer, nbytes, timeout);
733
Network::readNet(int fd, byte_t *buffer, int nbytes)
735
// GNASH_REPORT_FUNCTION;
736
return readNet(fd, buffer, nbytes, _timeout);
740
Network::readNet(int fd, byte_t *buffer, int nbytes, int timeout)
742
// GNASH_REPORT_FUNCTION;
749
log_debug (_("Trying to read %d bytes from fd #%d"), nbytes, fd);
754
gettimeofday(&tp, NULL);
755
read_start_time = static_cast<double>(tp.tv_sec)
756
+ static_cast<double>(tp.tv_usec*1e-6);
764
ret = select(fd+1, &fdset, NULL, NULL, NULL);
766
tval.tv_sec = timeout;
768
ret = select(fd+1, &fdset, NULL, NULL, &tval);
771
// If interupted by a system call, try again
772
if (ret == -1 && errno == EINTR) {
773
log_error (_("The socket for fd %d was interupted by a system call"), fd);
777
log_error (_("The socket for fd %d was never available for reading"), fd);
783
log_debug (_("The socket for fd %d timed out waiting to read"), fd);
788
ret = read(fd, buffer, nbytes);
789
// If we read zero bytes, the network is closed, as we returned from the select()
795
log_debug (_("read %d bytes from fd %d from port %d"), ret, fd, _port);
799
log_debug (_("%s: Read packet data from fd %d (%d bytes): \n%s"),
800
__FUNCTION__, fd, ret, hexify(buffer, ret, true));
809
// Write to the connection
811
Network::writeNet(amf::Buffer *buffer)
813
return writeNet(buffer->reference(), buffer->size());
817
Network::writeNet(const std::string& buffer)
819
return writeNet(reinterpret_cast<const byte_t *>(buffer.c_str()), buffer.size());
823
Network::writeNet(const byte_t *buffer, int nbytes)
825
return writeNet(_sockfd, buffer, nbytes, _timeout);
829
// Network::writeNet(const byte_t *buffer, int nbytes)
831
// return writeNet(_sockfd, buffer, nbytes, _timeout);
835
// Network::writeNet(int fd, const byte_t *buffer)
837
// return writeNet(fd, buffer, strlen(buffer), _timeout);
841
Network::writeNet(int fd, const byte_t *buffer, int nbytes)
843
return writeNet(fd, buffer, nbytes, _timeout);
847
Network::writeNet(int fd, const byte_t *buffer, int nbytes, int timeout)
853
// We need a writable, and not const point for byte arithmetic.
854
byte_t *bufptr = const_cast<byte_t *>(buffer);
857
// If we are debugging the tcp/ip timings, get the initial time.
860
gettimeofday(&starttime, 0);
867
// Reset the timeout value, since select modifies it on return
871
tval.tv_sec = timeout;
873
ret = select(fd+1, NULL, &fdset, NULL, &tval);
875
// If interupted by a system call, try again
876
if (ret == -1 && errno == EINTR) {
877
log_error (_("The socket for fd %d was interupted by a system call"), fd);
881
log_error (_("The socket for fd %d was never available for writing"), fd);
885
log_debug (_("The socket for fd %d timed out waiting to write"), fd);
889
ret = write(fd, bufptr, nbytes);
892
log_error (_("Wrote zero out of %d bytes to fd %d: %s"),
893
nbytes, fd, strerror(errno));
897
log_error (_("Couldn't write %d bytes to fd %d: %s"),
898
nbytes, fd, strerror(errno));
905
log_debug (_("wrote %d bytes to fd %d, expected %d"),
910
log_debug (_("wrote %d bytes to fd %d for port %d"),
918
log_debug (_("%s: Wrote packet data to fd %d: \n%s"),
919
__FUNCTION__, fd, hexify(buffer, ret, true));
927
gettimeofday(&endtime, 0);
929
if ((endtime.tv_sec - starttime.tv_sec) &&
930
endtime.tv_usec - starttime.tv_usec)
932
log_debug (_("took %d usec to write (%d bytes)"),
933
endtime.tv_usec - starttime.tv_usec, bytes_written);
943
Network::toggleDebug(bool val)
945
// Turn on our own debugging
948
// Turn on debugging for the utility methods
949
// recursive on all control paths,
950
// function will cause runtime stack overflow
952
// toggleDebug(true);
956
} // end of gnash namespace
960
// indent-tabs-mode: t