2 // Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010,
3 // 2011 Free Software Foundation, Inc
5 // This program is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation; either version 3 of the License, or
8 // (at your option) any later version.
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
15 // You should have received a copy of the GNU General Public License
16 // along with this program; if not, write to the Free Software
17 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21 #include "gnashconfig.h"
24 #include <boost/thread/mutex.hpp>
25 #include <boost/shared_ptr.hpp>
32 #include <sys/types.h>
37 #if defined(HAVE_WINSOCK_H) && !defined(__OS2__)
38 # include <winsock2.h>
40 # include <sys/stat.h>
42 # include <ws2tcpip.h>
44 # include <sys/ioctl.h>
45 # include <sys/time.h>
47 # include <sys/select.h>
48 # include <netinet/in.h>
49 # include <arpa/inet.h>
50 # include <sys/socket.h>
53 # include <sys/param.h>
54 # include <sys/select.h>
57 // This is for non-standard signal functions such as sigemptyset.
70 #include "GnashException.h"
72 #ifndef MAXHOSTNAMELEN
73 #define MAXHOSTNAMELEN 256
84 /// This is the main namespace for Gnash and it's libraries.
87 static const char *DEFAULTPROTO
= "tcp";
88 static const short DEFAULTPORT
= RTMP_PORT
;
91 #define INADDR_NONE 0xffffffff
94 static void cntrlc_handler(int sig
);
95 // this is set when we get a signal during a pselect() or ppoll()
96 static int sig_number
= 0;
108 // GNASH_REPORT_FUNCTION;
109 #if defined(HAVE_WINSOCK_H) && !defined(__OS2__)
110 WORD wVersionRequested
;
112 wVersionRequested
= MAKEWORD(1, 1); // Windows Sockets 1.1
113 if (WSAStartup( wVersionRequested
, &wsaData
) != 0) {
114 log_error(_("Could not find a usable WinSock DLL"));
123 // GNASH_REPORT_FUNCTION;
124 #if defined(HAVE_WINSOCK_H) && !defined(__OS2__)
131 // Description: Create a tcp/ip network server. This creates a server
132 // that listens for incoming socket connections. This
133 // supports IP aliasing on the host, and will sequntially
134 // look for IP address to bind this port to.
136 Network::createServer(void)
138 // GNASH_REPORT_FUNCTION;
147 return createServer(port
);
150 // FIXME: Should also support IPv6 (AF_INET6)
152 Network::createServer(short port
)
154 // GNASH_REPORT_FUNCTION;
156 struct protoent
*ppe
;
157 struct sockaddr_in sock_in
;
161 if (_listenfd
>= 2) {
162 log_debug("already connected to port %hd", port
);
166 const struct hostent
*host
= gethostbyname("localhost");
167 struct in_addr
*thisaddr
= reinterpret_cast<struct in_addr
*>(host
->h_addr_list
[0]);
168 _ipaddr
= thisaddr
->s_addr
;
169 memset(&sock_in
, 0, sizeof(sock_in
));
172 // Accept incoming connections only on our IP number
173 sock_in
.sin_addr
.s_addr
= thisaddr
->s_addr
;
175 // Accept incoming connections on any IP number
176 sock_in
.sin_addr
.s_addr
= INADDR_ANY
;
179 _ipaddr
= sock_in
.sin_addr
.s_addr
;
180 sock_in
.sin_family
= AF_INET
;
181 sock_in
.sin_port
= htons(port
);
183 if ((ppe
= getprotobyname(DEFAULTPROTO
)) == 0) {
184 log_error(_("unable to get protocol entry for %s"),
190 if ( strcmp(DEFAULTPROTO
, "udp") == 0) {
196 // Get a file descriptor for this socket connection
197 _listenfd
= socket(PF_INET
, type
, ppe
->p_proto
);
199 // error, wasn't able to create a socket
201 log_error(_("unable to create socket: %s"), strerror(errno
));
206 if (setsockopt(_listenfd
, SOL_SOCKET
, SO_REUSEADDR
,
207 (char *)&on
, sizeof(on
)) < 0) {
208 log_error(_("setsockopt SO_REUSEADDR failed"));
214 // in_addr_t nodeaddr;
215 // nodeaddr = inet_lnaof(*thisaddr);
216 while (retries
< 5) {
217 if (bind(_listenfd
, reinterpret_cast<struct sockaddr
*>(&sock_in
),
218 sizeof(sock_in
)) == -1) {
219 log_error(_("unable to bind to port %hd: %s"),
220 port
, strerror(errno
));
221 // inet_ntoa(sock_in.sin_addr), strerror(errno));
226 // char ascip[INET_ADDRSTRLEN];
227 // inet_ntop(sock_in.sin_family, &_ipaddr, ascip, INET_ADDRSTRLEN);
228 char *ascip
= ::inet_ntoa(sock_in
.sin_addr
);
229 log_debug(_("Server bound to service on %s, port %hd, using fd #%d"),
230 ascip
, ntohs(sock_in
.sin_port
),
234 if (type
== SOCK_STREAM
&& listen(_listenfd
, 5) < 0) {
235 log_error(_("unable to listen on port: %hd: %s "),
236 port
, strerror(errno
));
240 // We have a socket created
247 // Description: Accept a new network connection for the port we have
248 // created a server for.
249 // The default is to block.
251 Network::newConnection(void)
253 // GNASH_REPORT_FUNCTION;
255 return newConnection(true, _listenfd
);
259 Network::newConnection(int fd
)
261 // GNASH_REPORT_FUNCTION;
263 return newConnection(true, fd
);
267 Network::newConnection(bool block
)
269 // GNASH_REPORT_FUNCTION;
271 return newConnection(block
, _listenfd
);
275 Network::newConnection(bool block
, int fd
)
277 // GNASH_REPORT_FUNCTION;
279 struct sockaddr newfsin
;
285 alen
= sizeof(struct sockaddr_in
);
291 log_debug(_("Waiting to accept net traffic on fd #%d for port %d"), fd
, _port
);
295 struct timespec tval
;
296 sigset_t sigset
, blockset
, pending
;
297 sigemptyset(&blockset
);
298 // sigaddset(&blockset, SIGINT); /* Block SIGINT */
299 sigaddset(&blockset
, SIGPIPE
); /* Block SIGPIPE */
300 sigprocmask(SIG_BLOCK
, &blockset
, &sigset
);
306 // We use select to wait for the read file descriptor to be
307 // active, which means there is a client waiting to connect.
309 // also return on any input from stdin
311 // FD_SET(fileno(stdin), &fdset);
315 // Reset the timeout value, since select modifies it on return. To
316 // block, set the timeout to zero.
318 tval
.tv_sec
= _timeout
;
321 ret
= pselect(fd
+1, &fdset
, NULL
, NULL
, NULL
, &blockset
);
323 ret
= pselect(fd
+1, &fdset
, NULL
, NULL
, &tval
, &blockset
);
326 log_debug("Have a SIGINT interupt waiting!");
328 sigpending(&pending
);
329 if (sigismember(&pending
, SIGINT
)) {
330 log_debug("Have a pending SIGINT interupt waiting!");
332 sigwait(&blockset
, &sig
);
334 if (sigismember(&pending
, SIGPIPE
)) {
335 log_debug("Have a pending SIGPIPE interupt waiting!");
337 sigwait(&blockset
, &sig
);
343 ret
= select(fd
+1, &fdset
, NULL
, NULL
, NULL
);
345 ret
= select(fd
+1, &fdset
, NULL
, NULL
, &tval
);
349 if (FD_ISSET(0, &fdset
)) {
351 log_debug(_("There is a new network connection request."));
356 // If interrupted by a system call, try again
357 if (ret
== -1 && errno
== EINTR
) {
358 log_debug(_("The accept() socket for fd #%d was interrupted by a system call"), fd
);
362 log_debug(_("The accept() socket for fd #%d never was available"), fd
);
368 log_debug(_("The accept() socket for fd #%d timed out waitingfor data"), fd
);
375 #ifndef HAVE_WINSOCK_H
376 fcntl(_listenfd
, F_SETFL
, O_NONBLOCK
); // Don't let accept() block
378 _sockfd
= accept(fd
, &newfsin
, &alen
);
381 log_error(_("unable to accept: %s"), strerror(errno
));
386 log_debug(_("Accepting tcp/ip connection on fd #%d for port %d"), _sockfd
, _port
);
392 #if defined(_WIN32) || defined(__amigaos4__)
393 /* from sys/socket.h */
394 typedef unsigned short sa_family_t
;
397 #define UNIX_PATH_MAX 108
400 sa_family_t sun_family
; /* AF_UNIX */
401 char sun_path
[UNIX_PATH_MAX
]; /* pathname */
406 // Connect to a named pipe
408 Network::connectSocket(const string
&sockname
)
410 // GNASH_REPORT_FUNCTION;
412 struct sockaddr_un addr
;
418 addr
.sun_family
= AF_UNIX
;
419 // socket names must be 108 bytes or less as specifiec in sys/un.h.
420 strncpy(addr
.sun_path
, sockname
.c_str(), 100);
422 _sockfd
= ::socket(AF_UNIX
, SOCK_STREAM
, 0);
424 log_error(_("unable to create socket: %s"), strerror(errno
));
430 while (retries
-- > 0) {
431 // We use select to wait for the read file descriptor to be
432 // active, which means there is a client waiting to connect.
434 FD_SET(_sockfd
, &fdset
);
436 // Reset the timeout value, since select modifies it on return. To
437 // block, set the timeout to zero.
441 ret
= ::select(_sockfd
+1, &fdset
, NULL
, NULL
, &tval
);
443 // If interrupted by a system call, try again
444 if (ret
== -1 && errno
== EINTR
) {
445 log_debug(_("The connect() socket for fd %d was interrupted by a system call"),
451 log_debug(_("The connect() socket for fd %d never was available for writing"),
453 #ifdef HAVE_WINSOCK_H
454 ::shutdown(_sockfd
, 0); // FIXME: was SHUT_BOTH
456 ::shutdown(_sockfd
, SHUT_RDWR
);
462 log_error(_("The connect() socket for fd %d timed out waiting to write"),
468 ret
= ::connect(_sockfd
, reinterpret_cast<struct sockaddr
*>(&addr
), sizeof(addr
));
470 log_debug(_("\tsocket name %s for fd %d"), sockname
, _sockfd
);
476 log_error(_("The connect() socket for fd %d never was available for writing"),
486 #ifndef HAVE_WINSOCK_H
487 fcntl(_sockfd
, F_SETFL
, O_NONBLOCK
);
495 // Create a client connection to a tcp/ip based service
497 Network::createClient(void)
499 // GNASH_REPORT_FUNCTION;
508 return createClient("localhost", port
);
511 Network::createClient(short /* port */)
513 // GNASH_REPORT_FUNCTION;
519 Network::createClient(const string
&hostname
)
521 // GNASH_REPORT_FUNCTION;
530 return createClient(hostname
, port
);
534 Network::createClient(const string
&hostname
, short port
)
536 // GNASH_REPORT_FUNCTION;
538 struct sockaddr_in sock_in
;
543 char thishostname
[MAXHOSTNAMELEN
];
544 struct protoent
*proto
;
546 // assert( ! connected() );
552 log_debug(_("%s: to host %s at port %d"), __FUNCTION__
, hostname
, port
);
554 memset(&sock_in
, 0, sizeof(struct sockaddr_in
));
555 memset(&thishostname
, 0, MAXHOSTNAMELEN
);
556 if (hostname
.size() == 0) {
557 if (gethostname(thishostname
, MAXHOSTNAMELEN
) == 0) {
558 log_debug(_("The hostname for this machine is %s"), thishostname
);
560 log_debug(_("Couldn't get the hostname for this machine"));
565 const struct hostent
*hent
= ::gethostbyname(hostname
.c_str());
567 ::memcpy(&sock_in
.sin_addr
, hent
->h_addr
, hent
->h_length
);
569 sock_in
.sin_family
= AF_INET
;
570 sock_in
.sin_port
= ntohs(static_cast<short>(port
));
573 char ascip
[INET_ADDRSTRLEN
];
574 inet_ntop(sock_in
.sin_family
, &sock_in
.sin_addr
.s_addr
, ascip
, INET_ADDRSTRLEN
);
575 log_debug(_("The IP address for this client socket is %s"), ascip
);
578 proto
= ::getprotobyname("TCP");
580 _sockfd
= ::socket(PF_INET
, SOCK_STREAM
, proto
->p_proto
);
582 log_error(_("unable to create socket: %s"), strerror(errno
));
588 while (retries
-- > 0) {
589 // We use select to wait for the read file descriptor to be
590 // active, which means there is a client waiting to connect.
592 FD_SET(_sockfd
, &fdset
);
594 // Reset the timeout value, since select modifies it on return. To
595 // block, set the timeout to zero.
599 ret
= ::select(_sockfd
+1, &fdset
, NULL
, NULL
, &tval
);
601 // If interrupted by a system call, try again
602 if (ret
== -1 && errno
== EINTR
) {
603 log_debug(_("The connect() socket for fd %d was interrupted "
604 "by a system call"), _sockfd
);
609 log_debug(_("The connect() socket for fd %d never was "
610 "available for writing"), _sockfd
);
611 #ifdef HAVE_WINSOCK_H
612 ::shutdown(_sockfd
, 0); // FIXME: was SHUT_BOTH
614 ::shutdown(_sockfd
, SHUT_RDWR
);
622 #ifdef HAVE_WINSOCK_H
623 ::shutdown(_sockfd
, 0); // FIXME: was SHUT_BOTH
625 ::shutdown(_sockfd
, SHUT_RDWR
);
627 log_error(_("The connect() socket for fd %d timed out waiting "
628 "to write"), _sockfd
);
634 ret
= ::connect(_sockfd
,
635 reinterpret_cast<struct sockaddr
*>(&sock_in
),
639 char *ascip
= ::inet_ntoa(sock_in
.sin_addr
);
640 // char ascip[INET_ADDRSTRLEN];
641 // inet_ntop(sock_in.sin_family, &sock_in.sin_addr.s_addr, ascip, INET_ADDRSTRLEN);
642 log_debug(_("\tport %d at IP %s for fd %d"), port
,
649 log_error(_("The connect() socket for fd %d never was "
650 "available for writing"), _sockfd
);
651 #ifdef HAVE_WINSOCK_H
652 ::shutdown(_sockfd
, 0); // FIXME: was SHUT_BOTH
654 ::shutdown(_sockfd
, SHUT_RDWR
);
666 printf("\tConnected at port %d on IP %s for fd #%d", port
,
667 ::inet_ntoa(sock_in
.sin_addr
), _sockfd
);
669 #ifndef HAVE_WINSOCK_H
670 fcntl(_sockfd
, F_SETFL
, O_NONBLOCK
);
682 // GNASH_REPORT_FUNCTION;
684 if ((_sockfd
> 0) && (_connected
)) {
694 Network::closeNet(int sockfd
)
696 // GNASH_REPORT_FUNCTION;
700 // If we can't close the socket, other processes must be
701 // locked on it, so we wait a second, and try again. After a
702 // few tries, we give up, cause there must be something
709 while (retries
< 3) {
711 // Shutdown the socket connection
713 if (shutdown(sockfd
, SHUT_RDWR
) < 0) {
714 if (errno
!= ENOTCONN
) {
715 cerr
<< "WARNING: Unable to shutdown socket for fd #"
716 << sockfd
<< strerror(errno
) << endl
;
718 cerr
<< "The socket using fd #" << sockfd
719 << " has been shut down successfully." << endl
;
724 if (::close(sockfd
) < 0) {
725 // If we have a bad file descriptor, it's because
726 // this got closed already, usually by another
727 // thread being paranoid.
728 if (errno
!= EBADF
) {
729 log_error(_("Unable to close the socket for fd #%d: %s"),
730 sockfd
, strerror(errno
));
732 #ifndef HAVE_WINSOCK_H
737 log_debug(_("Closed the socket on fd #%d"), sockfd
);
744 // Description: Close an open socket connection.
746 Network::closeConnection(void)
748 // GNASH_REPORT_FUNCTION;
750 closeConnection(_sockfd
);
752 closeConnection(_listenfd
);
760 Network::closeConnection(int fd
)
762 // GNASH_REPORT_FUNCTION;
766 log_debug("%s: Closed fd #%d", __FUNCTION__
, fd
);
773 boost::shared_ptr
<cygnal::Buffer
>
776 // GNASH_REPORT_FUNCTION;
777 boost::shared_ptr
<cygnal::Buffer
> buffer(new cygnal::Buffer
);
778 int ret
= readNet(*buffer
);
785 // Read from the connection
787 Network::readNet(int fd
, cygnal::Buffer
&buffer
)
789 // GNASH_REPORT_FUNCTION;
790 int ret
= readNet(fd
, buffer
.reference(), buffer
.size(), _timeout
);
799 Network::readNet(int fd
, cygnal::Buffer
*buffer
)
801 // GNASH_REPORT_FUNCTION;
802 int ret
= readNet(fd
, buffer
->reference(), buffer
->size(), _timeout
);
804 buffer
->setSeekPointer(buffer
->reference() + ret
);
811 Network::readNet(cygnal::Buffer
&buffer
)
813 // GNASH_REPORT_FUNCTION;
814 int ret
= readNet(_sockfd
, buffer
, _timeout
);
820 Network::readNet(cygnal::Buffer
&buffer
, int timeout
)
822 // GNASH_REPORT_FUNCTION;
823 int ret
= readNet(_sockfd
, buffer
.reference(), buffer
.size(), timeout
);
825 buffer
.resize(ret
); // FIXME: why does this corrupt
832 Network::readNet(int fd
, cygnal::Buffer
&buffer
, int timeout
)
834 // GNASH_REPORT_FUNCTION;
835 int ret
= readNet(fd
, buffer
.reference(), buffer
.size(), timeout
);
836 buffer
.setSeekPointer(ret
);
839 buffer
.resize(ret
); // FIXME: why does this corrupt
847 Network::readNet(byte_t
*data
, int nbytes
)
849 // GNASH_REPORT_FUNCTION;
850 return readNet(_sockfd
, data
, nbytes
, _timeout
);
854 Network::readNet(byte_t
*data
, int nbytes
, int timeout
)
856 // GNASH_REPORT_FUNCTION;
857 return readNet(_sockfd
, data
, nbytes
, timeout
);
861 Network::readNet(int fd
, byte_t
*data
, int nbytes
)
863 // GNASH_REPORT_FUNCTION;
864 return readNet(fd
, data
, nbytes
, _timeout
);
868 Network::readNet(int fd
, byte_t
*buffer
, int nbytes
, int timeout
)
870 // GNASH_REPORT_FUNCTION;
875 // boost::mutex::scoped_lock lock(_net_mutex);
878 log_debug (_("Trying to read %d bytes from fd #%d"), nbytes
, fd
);
883 gettimeofday(&tp
, NULL
);
884 read_start_time
= static_cast<double>(tp
.tv_sec
)
885 + static_cast<double>(tp
.tv_usec
*1e-6);
893 struct timespec tval
;
894 sigset_t pending
, blockset
;
895 sigemptyset(&blockset
);
896 // sigaddset(&blockset, SIGINT); /* Block SIGINT */
897 // sigaddset(&blockset, SIGPIPE); /* Block SIGPIPE */
898 sigprocmask(SIG_BLOCK
, &blockset
, NULL
);
900 // Trap ^C (SIGINT) so we can kill all the threads
901 // struct sigaction act;
902 // act.sa_handler = cntrlc_handler;
904 // sigemptyset(&act.sa_mask);
905 // sigaction (SIGINT, &act, NULL);
911 ret
= pselect(fd
+1, &fdset
, NULL
, NULL
, NULL
, &blockset
);
913 ret
= select(fd
+1, &fdset
, NULL
, NULL
, NULL
);
917 tval
.tv_sec
= timeout
;
919 ret
= pselect(fd
+1, &fdset
, NULL
, NULL
, &tval
, &blockset
);
920 sigpending(&pending
);
921 if (sigismember(&pending
, SIGINT
)) {
922 log_debug("Have a pending SIGINT interupt waiting!");
924 sigwait(&blockset
, &sig
);
925 cntrlc_handler(SIGINT
);
927 if (sigismember(&pending
, SIGPIPE
)) {
928 log_debug("Have a pending SIGPIPE interupt waiting!");
930 sigwait(&blockset
, &sig
);
931 cntrlc_handler(SIGINT
);
934 tval
.tv_sec
= timeout
;
936 ret
= select(fd
+1, &fdset
, NULL
, NULL
, &tval
);
940 // If interrupted by a system call, try again
941 if (ret
== -1 && errno
== EINTR
) {
942 log_error (_("The socket for fd #%d was interrupted by a system call"), fd
);
946 log_error (_("The socket for fd #%d was never available for reading"), fd
);
952 log_debug (_("The socket for #fd %d timed out waiting to read"), fd
);
959 ret
= _ssl
->sslRead(buffer
, nbytes
);
961 ret
= read(fd
, buffer
, nbytes
);
964 ret
= read(fd
, buffer
, nbytes
);
967 // If we read zero bytes, the network may be closed, as we returned from the select()
969 log_error (_("The socket for fd #%d was never available for reading data"), fd
);
975 log_debug (_("The socket for #fd %d timed out waiting to read data"), fd
);
981 log_debug (_("read %d bytes from fd #%d from port %d"), ret
, fd
, _port
);
985 log_debug (_("%s: Read packet data from fd #%d (%d bytes): \n%s"),
986 __FUNCTION__
, fd
, ret
, hexify(buffer
, ret
, true));
995 // Write to the connection
997 Network::writeNet(cygnal::Buffer
*buffer
)
999 // GNASH_REPORT_FUNCTION;
1000 return writeNet(buffer
->reference(), buffer
->allocated());
1004 Network::writeNet(int fd
, cygnal::Buffer
*buffer
)
1006 // GNASH_REPORT_FUNCTION;
1007 return writeNet(fd
, buffer
->reference(), buffer
->allocated());
1010 // Write to the connection
1012 Network::writeNet(cygnal::Buffer
&buffer
)
1014 // GNASH_REPORT_FUNCTION;
1015 return writeNet(buffer
.reference(), buffer
.allocated());
1018 // Write to the connection
1020 Network::writeNet(int fd
, cygnal::Buffer
&buffer
)
1022 // GNASH_REPORT_FUNCTION;
1023 return writeNet(fd
, buffer
.reference(), buffer
.allocated());
1027 Network::writeNet(const std::string
& data
)
1029 // GNASH_REPORT_FUNCTION;
1030 return writeNet(reinterpret_cast<const byte_t
*>(data
.c_str()), data
.size());
1034 Network::writeNet(const byte_t
*data
, int nbytes
)
1036 // GNASH_REPORT_FUNCTION;
1037 return writeNet(_sockfd
, data
, nbytes
, _timeout
);
1041 // Network::writeNet(const byte_t *buffer, int nbytes)
1043 // return writeNet(_sockfd, buffer, nbytes, _timeout);
1047 // Network::writeNet(int fd, const byte_t *buffer)
1049 // return writeNet(fd, buffer, strlen(buffer), _timeout);
1053 Network::writeNet(int fd
, const byte_t
*data
, int nbytes
)
1055 // GNASH_REPORT_FUNCTION;
1056 return writeNet(fd
, data
, nbytes
, _timeout
);
1060 Network::writeNet(int fd
, const byte_t
*buffer
, int nbytes
, int timeout
)
1062 // GNASH_REPORT_FUNCTION;
1067 boost::mutex::scoped_lock
lock(_net_mutex
);
1069 // We need a writable, and not const point for byte arithmetic.
1070 byte_t
*bufptr
= const_cast<byte_t
*>(buffer
);
1073 // If we are debugging the tcp/ip timings, get the initial time.
1076 gettimeofday(&starttime
, 0);
1084 struct timespec tval
;
1085 sigset_t pending
, blockset
; //, emptyset;
1086 sigemptyset(&blockset
);
1087 // sigaddset(&blockset, SIGINT); /* Block SIGINT */
1088 sigaddset(&blockset
, SIGPIPE
);
1089 sigprocmask(SIG_BLOCK
, &blockset
, NULL
);
1091 struct timeval tval
;
1093 // Reset the timeout value, since select modifies it on return
1098 tval
.tv_sec
= timeout
;
1100 ret
= pselect(fd
+1, NULL
, &fdset
, NULL
, &tval
, &blockset
);
1101 sigpending(&pending
);
1102 if (sigismember(&pending
, SIGINT
)) {
1103 log_debug("Have a pending SIGINT interupt waiting!");
1105 sigwait(&blockset
, &sig
);
1106 cntrlc_handler(SIGINT
);
1109 tval
.tv_sec
= timeout
;
1111 ret
= select(fd
+1, NULL
, &fdset
, NULL
, &tval
);
1114 // If interrupted by a system call, try again
1115 if (ret
== -1 && errno
== EINTR
) {
1116 log_error (_("The socket for fd #%d was interrupted by a system call"), fd
);
1120 log_error (_("The socket for fd #%d was never available for writing"), fd
);
1124 log_debug (_("The socket for fd #%d timed out waiting to write"), fd
);
1130 ret
= _ssl
->sslWrite(buffer
, nbytes
);
1132 ret
= write(fd
, bufptr
, nbytes
);
1135 ret
= write(fd
, bufptr
, nbytes
);
1138 log_error (_("Wrote zero out of %d bytes to fd #%d: %s"),
1139 nbytes
, fd
, strerror(errno
));
1143 log_error (_("Couldn't write %d bytes to fd #%d: %s"),
1144 nbytes
, fd
, strerror(errno
));
1149 if (ret
!= nbytes
) {
1151 log_debug (_("wrote %d bytes to fd #%d, expected %d"),
1156 log_debug (_("wrote %d bytes to fd #%d for port %d"),
1164 log_debug (_("%s: Wrote packet data to fd #%d: \n%s"),
1165 __FUNCTION__
, fd
, hexify(buffer
, ret
, true));
1173 gettimeofday(&endtime
, 0);
1175 if ((endtime
.tv_sec
- starttime
.tv_sec
) &&
1176 endtime
.tv_usec
- starttime
.tv_usec
)
1178 log_debug (_("took %d usec to write (%d bytes)"),
1179 endtime
.tv_usec
- starttime
.tv_usec
, bytes_written
);
1189 Network::addPollFD(struct pollfd
&fd
, Network::entry_t
*func
)
1191 // GNASH_REPORT_FUNCTION;
1193 log_debug("%s: adding fd #%d to pollfds", __PRETTY_FUNCTION__
, fd
.fd
);
1194 boost::mutex::scoped_lock
lock(_poll_mutex
);
1195 _handlers
[fd
.fd
] = func
;
1196 _pollfds
.push_back(fd
);
1201 Network::addPollFD(struct pollfd
&fd
)
1203 // GNASH_REPORT_FUNCTION;
1204 log_debug("%s: adding fd #%d to pollfds", __PRETTY_FUNCTION__
, fd
.fd
);
1205 boost::mutex::scoped_lock
lock(_poll_mutex
);
1206 _pollfds
.push_back(fd
);
1211 &Network::getPollFD(int index
)
1213 // GNASH_REPORT_FUNCTION;
1214 boost::mutex::scoped_lock
lock(_poll_mutex
);
1215 return _pollfds
[index
];
1219 Network::getPollFDPtr()
1221 // GNASH_REPORT_FUNCTION;
1222 boost::mutex::scoped_lock
lock(_poll_mutex
);
1223 return &_pollfds
[0];
1227 Network::erasePollFD(int fd
)
1229 // GNASH_REPORT_FUNCTION;
1230 log_debug("%s: erasing fd #%d from pollfds", __PRETTY_FUNCTION__
, fd
);
1231 boost::mutex::scoped_lock
lock(_poll_mutex
);
1232 if (_pollfds
.size() > 0) {
1233 vector
<struct pollfd
>::iterator it
;
1234 for (it
=_pollfds
.begin(); it
<_pollfds
.end(); it
++) {
1235 if ((*it
).fd
== fd
) {
1244 Network::erasePollFD(vector
<struct pollfd
>::iterator
&itt
)
1246 // GNASH_REPORT_FUNCTION;
1247 boost::mutex::scoped_lock
lock(_poll_mutex
);
1248 if (_pollfds
.size() == 1) {
1251 _pollfds
.erase(itt
);
1256 Network::addEntry(int fd
, Network::entry_t
*func
)
1258 // GNASH_REPORT_FUNCTION;
1259 boost::mutex::scoped_lock
lock(_poll_mutex
);
1260 _handlers
[fd
] = func
;
1264 Network::getEntry(int fd
)
1266 // GNASH_REPORT_FUNCTION;
1267 boost::mutex::scoped_lock
lock(_poll_mutex
);
1268 return _handlers
[fd
];
1271 boost::shared_ptr
<std::vector
<struct pollfd
> >
1272 Network::waitForNetData(int limit
, struct pollfd
*fds
)
1274 // GNASH_REPORT_FUNCTION;
1276 boost::shared_ptr
<vector
<struct pollfd
> > hits(new vector
<struct pollfd
>);
1278 log_debug("%s: waiting for %d fds", __FUNCTION__
, limit
);
1280 if ((fds
== 0) || (limit
== 0)) {
1284 int timeout
= _timeout
;
1289 struct timespec tval
;
1290 sigset_t pending
, blockset
;
1291 sigemptyset(&blockset
); /* Block SIGINT */
1292 // sigaddset(&blockset, SIGINT);
1293 // sigaddset(&blockset, SIGPIPE);
1294 sigprocmask(SIG_BLOCK
, &blockset
, NULL
);
1296 tval
.tv_sec
= 5; // FIXME: was _timeout;
1298 int ret
= ppoll(fds
, limit
, &tval
, &blockset
);
1299 sigpending(&pending
);
1300 if (sigismember(&pending
, SIGINT
)) {
1301 log_debug("Have a pending SIGINT interupt waiting!");
1303 sigwait(&blockset
, &sig
);
1307 int ret
= poll(fds
, limit
, _timeout
);
1310 struct timeval tval
;
1311 tval
.tv_sec
= timeout
;
1313 int ret
= select(limit
+1, &fdset
, NULL
, NULL
, &tval
);
1317 log_debug("Poll returned: %d, timeout is: %d", ret
, _timeout
);
1320 for (int i
= 0; i
<limit
; i
++) {
1321 // If we get this event, the other end of the connection has been shut down
1323 if (fds
[i
].revents
&POLLPRI
) {
1324 log_debug("%s: Revents has a POLLPRI set 0x%x for fd #%d",
1325 __FUNCTION__
, fds
[i
].revents
, fds
[i
].fd
);
1327 if (fds
[i
].revents
& POLLRDNORM
) {
1328 log_debug("%s: Revents has a POLLRDNORM set 0x%x for fd #%d",
1329 __FUNCTION__
, fds
[i
].revents
, fds
[i
].fd
);
1331 if (fds
[i
].revents
& POLLHUP
) {
1332 log_debug("%s: Revents has a POLLHUP set 0x%x for fd #%d",
1333 __FUNCTION__
, fds
[i
].revents
, fds
[i
].fd
);
1337 if (fds
[i
].revents
& POLLERR
) {
1338 log_debug("%s: Revents has a POLLERR set 0x%x for fd #%d",
1339 __FUNCTION__
, fds
[i
].revents
, fds
[i
].fd
);
1341 if (fds
[i
].revents
& POLLHUP
) {
1342 log_debug("%s: Revents has a POLLHUP set 0x%x for fd #%d",
1343 __FUNCTION__
, fds
[i
].revents
, fds
[i
].fd
);
1345 if (fds
[i
].revents
& POLLNVAL
) {
1346 log_debug("%s: Revents has a POLLNVAL set 0x%x for fd #%d",
1347 __FUNCTION__
, fds
[i
].revents
, fds
[i
].fd
);
1348 // throw GnashException("Polling an invalid file descritor");
1350 if (fds
[i
].revents
& POLLIN
) {
1351 log_debug("%s: Revents has a POLLIN set 0x%x for fd #%d",
1352 __FUNCTION__
, fds
[i
].revents
, fds
[i
].fd
);
1354 if (fds
[i
].revents
& POLLMSG
) {
1355 log_debug("%s: Revents has a POLLMSG set 0x%x for fd #%d",
1356 __FUNCTION__
, fds
[i
].revents
, fds
[i
].fd
);
1358 if (fds
[i
].revents
& POLLREMOVE
) {
1359 log_debug("%s: Revents has a POLLREMOVE set 0x%x for fd #%d",
1360 __FUNCTION__
, fds
[i
].revents
, fds
[i
].fd
);
1362 if (fds
[i
].revents
& POLLRDHUP
) {
1363 log_debug("%s: Revents has a POLLRDHUP set 0x%x for fd #%d",
1364 __FUNCTION__
, fds
[i
].revents
, fds
[i
].fd
);
1365 // throw GnashException("Connection dropped from client side.");
1368 // if ((fds[i].revents & POLLIN) || (fds[i].revents & POLLRDHUP)) {
1369 hits
->push_back(fds
[i
]);
1370 // // If we got as many matches as were seen by poll(), then
1371 // // stop searching the rest of the items in the array.
1372 // if (hits->size() == ret) {
1376 // log_debug("No data on fd #%d, revents is 0x%x", fds[i].fd, fds[i].revents);
1385 Network::waitForNetData(vector
<int> &data
)
1387 // GNASH_REPORT_FUNCTION;
1395 for (size_t i
= 0; i
<data
.size(); i
++) {
1396 FD_SET(data
[i
], &fdset
);
1397 if (data
[i
] > max
) {
1401 return waitForNetData(max
+1, fdset
);
1408 Network::waitForNetData(int limit
, fd_set files
)
1410 // GNASH_REPORT_FUNCTION;
1412 // select modifies the set of file descriptors, and we don't
1413 // want to modify the one passed as an argument, so we make a copy.
1414 fd_set fdset
= files
;
1416 // Reset the timeout value, since select modifies it on return
1417 int timeout
= _timeout
;
1421 #ifdef HAVE_PSELECT_XX
1422 struct timespec tval
;
1423 sigset_t pending
, sigmask
;
1424 sigprocmask(SIG_BLOCK
, &sigmask
, NULL
);
1427 tval
.tv_nsec
= timeout
* 1000000000;
1428 int ret
= pselect(limit
+1, &fdset
, NULL
, NULL
, &tval
, &sigmask
);
1429 sigpending(&pending
);
1430 if (sigismember(&pending
, SIGINT
)) {
1431 log_debug("Have a pending SIGINT interupt waiting!");
1433 sigwait(&sigmask
, &sig
);
1435 if (sigismember(&pending
, SIGPIPE
)) {
1436 log_debug("Have a pending SIGPIPE interupt waiting!");
1438 sigwait(&sigmask
, &sig
);
1441 struct timeval tval
;
1443 tval
.tv_usec
= timeout
* 1000; // was 1000000
1444 int ret
= select(limit
+1, &fdset
, NULL
, NULL
, &tval
);
1446 // If interrupted by a system call, try again
1447 if (ret
== -1 && errno
== EINTR
) {
1448 log_error (_("Waiting for data was interrupted by a system call"));
1452 log_error (_("Waiting for data for fdset, was never available for reading"));
1459 // log_debug (_("Waiting for data for fdset, timed out waiting for data"));
1466 log_error("select() got an error: %s.", strerror(errno
));
1470 log_network("select() saw activity on %d file descriptors.", ret
);
1477 Network::operator = (Network
&net
)
1479 GNASH_REPORT_FUNCTION
;
1481 // the file descriptor used for reading and writing
1482 _sockfd
= net
.getFileFd();
1483 // the file descriptor used to listen for new connections
1484 _listenfd
= net
.getListenFd();
1485 _port
= net
.getPort();
1486 _portstr
= net
.getPortStr();
1487 _url
= net
.getURL();
1488 _protocol
= net
.getProtocol();
1489 _host
= net
.getHost();
1490 _path
= net
.getPath();
1491 _connected
= net
.connected();
1492 _debug
= net
.netDebug();
1493 _timeout
= net
.getTimeout();
1498 Network::toggleDebug(bool val
)
1500 // Turn on our own debugging
1503 // Turn on debugging for the utility methods
1504 // recursive on all control paths,
1505 // toggleDebug(true);
1510 Network::initSSL(std::string
&hostname
)
1512 GNASH_REPORT_FUNCTION
;
1514 initSSL(hostname
, nothing
);
1518 Network::initSSL(std::string
&hostname
, std::string
&password
)
1520 GNASH_REPORT_FUNCTION
;
1523 initSSL(hostname
, password
, nothing
, nothing
, nothing
, true);
1527 Network::initSSL(std::string
&hostname
, std::string
&password
, bool auth
)
1529 GNASH_REPORT_FUNCTION
;
1532 initSSL(hostname
, password
, nothing
, nothing
, nothing
, auth
);
1536 Network::initSSL(std::string
&hostname
, std::string
&passwd
,
1537 std::string
&keyfile
, std::string
&calist
,
1538 std::string
&rootpath
, bool auth
)
1540 GNASH_REPORT_FUNCTION
;
1542 // FIXME: make sure we have a connection
1545 if ((_sockfd
= createClient(hostname
, SSL_PORT
) == false)) {
1546 log_error("Can't connect to server %s", hostname
);
1552 _ssl
.reset(new SSLClient
);
1555 if (!hostname
.empty()) {
1556 _ssl
->setHostname(hostname
);
1558 log_debug("Using default hostname: \"%s\"", _host
);
1560 if (!keyfile
.empty()) {
1561 _ssl
->setKeyfile(keyfile
);
1563 log_debug("Using default keyfile: \"%s\"", _ssl
->getKeyfile());
1565 if (!calist
.empty()) {
1566 _ssl
->setCAlist(calist
);
1568 log_debug("Using default CA List: \"%s\"", _ssl
->getCAlist());
1571 if (!passwd
.empty()) {
1572 _ssl
->setPassword(passwd
);
1574 log_debug("Using default Password: \"%s\"", _ssl
->getPassword());
1576 if (!rootpath
.empty()) {
1577 _ssl
->setRootPath(rootpath
);
1579 log_debug("Using default Root Path to PEM files: \"%s\"",
1580 _ssl
->getRootPath());
1583 if (_ssl
->sslConnect(_sockfd
)) {
1584 log_debug("Connected to SSL server");
1586 log_error("Couldn't connect to SSL server");
1590 // If we got this far, everthing worked
1595 // Use an ioctl() to see how many bytes are in the network buffers.
1597 Network::sniffBytesReady(int fd
)
1599 // GNASH_REPORT_FUNCTION;
1606 struct timeval tval
;
1609 if (select(fd
+1, &fdset
, NULL
, NULL
, &tval
)) {
1610 if (FD_ISSET(fd
, &fdset
)) {
1612 ioctl(fd
, FIONREAD
, &bytes
);
1614 ioctlSocket(fd
, FIONREAD
, &bytes
);
1619 log_network("#%d bytes waiting in kernel network buffer.", bytes
);
1624 // Trap Control-C so we can cleanly exit
1626 cntrlc_handler (int sig
)
1628 GNASH_REPORT_FUNCTION
;
1630 log_debug(_("Got an %d interrupt while blocked on pselect()"), sig
);
1634 } // end of gnash namespace
1638 // indent-tabs-mode: t