nagachika
2583078951
merge revision(s) r45084: [Backport #9547 ]
...
* ext/socket/init.c (wait_connectable): break if the socket is
writable to avoid infinite loops on FreeBSD and other platforms
which conforms to SUSv3. This problem cannot be reproduced with
loopback interfaces, so it's hard to write test code.
rsock_connect() and wait_connectable() are overly complicated, so
they should be refactored, but I commit this fix as a workaround
for the release of Ruby 1.9.3 scheduled on Feb 24.
[ruby-core:60940] [Bug #9547 ]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_2_0_0@45103 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2014-02-22 04:17:51 +00:00
nagachika
8d087aa871
merge revision(s) 40136: [Backport #9084 ]
...
* ext/socket/init.c (cloexec_accept): Fix a compile error on
Debian GNU/kFreeBSD. Consider HAVE_ACCEPT4 is defined
but SOCK_CLOEXEC is not defined.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_2_0_0@43649 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-11-11 14:55:35 +00:00
nobu
a9cbe8c721
init.c: declaration-after-statement
...
* ext/socket/init.c (cloexec_accept): fix declaration-after-statement.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@39040 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-02-04 06:19:40 +00:00
akr
1ff38a5bbf
* ext/socket/basicsocket.c (bsock_getsockname): ignore truncated
...
part of socket address.
(bsock_getpeername): ditto.
(bsock_local_address): ditto.
(bsock_remote_address): ditto.
* ext/socket/unixsocket.c (unix_path): ditto.
(unix_addr): ditto.
(unix_peeraddr): ditto.
* ext/socket/init.c (cloexec_accept): ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@38993 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-01-30 12:01:51 +00:00
usa
91987f6b04
* ext/socket/{basicksocket,init,udpsocket}.c: revert some parts of
...
r36944. it breaks mswin/mingw ruby and brought into many many
crashes.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@36946 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2012-09-10 01:41:59 +00:00
kosaki
84c77c1520
* ext/socket/basicsocket.c (rsock_bsock_send):
...
avoid unnecessary select() calls before doing I/O
Patch by Eric Wong. [Feature #4538 ] [ruby-core:35586]
* ext/socket/init.c (rsock_s_recvfrom): ditto.
* ext/socket/init.c (rsock_s_accept): ditto.
* ext/socket/udpsocket.c (udp_send): ditto.
* io.c (io_fflush): ditto.
* io.c (io_binwrite): ditto.
* io.c (rb_io_syswrite): ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@36944 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2012-09-09 17:29:12 +00:00
usa
2574b80d83
* ext/socket/init.c (rsock_init_sock): need to update max fd on all
...
platforms.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@36462 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2012-07-19 05:20:08 +00:00
akr
385a7d4594
* ext/socket/init.c (rsock_socket0): don't clear try_sock_cloexec if
...
SOCK_CLOEXEC is not a reason for EINVAL.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@33639 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2011-11-05 08:56:50 +00:00
akr
0e68c46e2d
* ext/socket/init.c (rsock_socket0): extract single socket() call with
...
CLOEXEC handling from rsock_socket.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@33637 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2011-11-05 06:46:02 +00:00
nagachika
a0b22b1a39
* ext/socket/init.c (rsock_socket): set close-on-exec flag when
...
SOCK_CLOEXEC is not available.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@33619 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2011-11-03 13:14:48 +00:00
akr
c16f98ab0a
* io.c (rb_maygvl_fd_fix_cloexec): renamed from fd_set_cloexec.
...
* internal.h (rb_maygvl_fd_fix_cloexec): declared.
* ext/socket/init.c (cloexec_accept): use rb_maygvl_fd_fix_cloexec.
(rsock_s_accept_nonblock): use rb_update_max_fd.
(rsock_s_accept): use rb_update_max_fd.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@33598 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2011-11-01 03:04:03 +00:00
akr
5dbc3d1e79
* ext/socket/init.c (cloexec_accept): new function to use accept4 if
...
available.
(rsock_s_accept_nonblock): use cloexec_accept.
(accept_blocking): ditto.
* ext/socket/extconf.rb: check accept4.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@33596 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2011-10-31 23:26:19 +00:00
akr
1a8fbff3db
* ext/socket/init.c (rsock_socket): use SOCK_CLOEXEC if available.
...
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@33589 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2011-10-31 14:38:50 +00:00
akr
1a70dfe6f4
* include/ruby/intern.h (rb_fd_fix_cloexec): renamed from
...
rb_fd_set_cloexec.
* io.c: follow the above renaming.
* ext/pty/pty.c: ditto.
* ext/socket/init.c: ditto.
* ext/socket/socket.c: ditto.
* ext/socket/ancdata.c: ditto.
* ext/socket/unixsocket.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@33585 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2011-10-31 12:49:16 +00:00
akr
b574a4d4a1
* include/ruby/intern.h (rb_fd_set_cloexec): declared.
...
* io.c (rb_fd_set_cloexec): new function.
(ruby_dup): call rb_fd_set_cloexec to set close-on-exec flag.
(rb_sysopen_internal): ditto.
(rb_pipe): ditto.
(io_reopen): ditto.
(io_cntl): ditto.
* process.c (rb_f_exec): change the default :close_others option to
true.
(rb_f_system): ditto.
(move_fds_to_avoid_crash): call rb_fd_set_cloexec to set
close-on-exec flag.
(ruby_setsid): ditto.
(rb_daemon): ditto.
* thread_pthread.c (rb_thread_create_timer_thread): call
rb_fd_set_cloexec to set close-on-exec flag.
* ruby.c (load_file_internal): ditto.
* file.c (rb_file_s_truncate): ditto.
(file_load_ok): ditto.
* random.c (fill_random_seed): ditto.
* ext/pty/pty.c (chfunc): ditto.
(get_device_once): ditto.
* ext/openssl/ossl_bio.c (ossl_obj2bio): ditto.
* ext/socket/init.c (rsock_socket): ditto.
(rsock_s_accept_nonblock): ditto.
(rsock_s_accept): ditto.
* ext/socket/socket.c (rsock_sock_s_socketpair): ditto.
* ext/socket/ancdata.c (discard_cmsg): ditto.
(make_io_for_unix_rights): ditto.
* ext/socket/unixsocket.c (unix_recv_io): ditto.
* ext/io/console/console.c (console_dev): ditto.
[ruby-core:38140] [Feature #5041 ]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@33507 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2011-10-22 09:58:15 +00:00
drbrain
1297942451
* ext/socket: Make Socket documentation appear. Add documentation for
...
Socket, TCPServer, SOCKSSocket. Patch by Sylvain Daubert.
[Ruby 1.9 - Feature #5182 ]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@32977 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2011-08-15 23:08:39 +00:00
akr
b41ccc4a9c
* include/ruby/intern.h (rb_update_max_fd): declaration moved from
...
internal.h.
* file.c: ditto.
* io.c: call rb_update_max_fd for each new fds.
* process.c: ditto.
* random.c: ditto.
* ruby.c: ditto.
* ext/io/console/console.c: ditto.
* ext/openssl/ossl_bio.c: ditto.
* ext/pty/pty.c: ditto.
* ext/socket/init.c: ditto.
* ext/socket/socket.c: ditto.
* ext/socket/ancdata.c: ditto.
* ext/socket/unixsocket.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@32587 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2011-07-20 13:26:10 +00:00
kosaki
9851b0ce2f
* ext/socket/init.c (wait_connectable): fix error handling code.
...
RB_WAITFD_OUT is turned on even though an error occur.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@31424 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2011-05-04 02:44:28 +00:00
kosaki
82b2e80120
* ext/socket/init.c (wait_connectable): use rb_wait_for_single_fd().
...
The patch was written by Eric Wong. [Ruby 1.9 - Feature #4531 ]
* ext/socket/init.c (try_wait_connectable, wait_connectable_ensure):
removed.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@31422 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2011-05-04 01:12:04 +00:00
kosaki
49b4510cd1
* ext/socket/init.c (rsock_connect): add to care EINTR. based
...
on a patch from Eric Wong at [ruby-core:35621][Bug #4555 ]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@31405 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2011-05-01 15:38:53 +00:00
kosaki
2d2544c8e6
* include/ruby/intern.h (rb_thread_select): mark as deprecated.
...
* ext/io/wait/wait.c (wait_readable): use rb_thread_fd_select
instead of rb_thread_select.
* ext/socket/init.c (wait_connectable0): ditto.
* ext/readline/readline.c (readline_event): ditto.
* io.c (rb_io_wait_readable, wait_readable, rb_io_wait_writable,
wait_writable): ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@31394 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2011-04-30 11:15:15 +00:00
nobu
58b325366d
* thread.c (rb_thread_io_blocking_region): new function to run
...
blocking region with GIL released, for fd.
* thread.c (rb_thread_fd_close): implement. [ruby-core:35203]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@30852 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2011-02-12 05:44:23 +00:00
nobu
b736c9b5dc
* ext/socket/init.c (rsock_init_sock): conditionally used variable.
...
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@29464 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2010-10-12 14:54:02 +00:00
nobu
4822d20cc5
* ext/socket: fixed types.
...
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@27529 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2010-04-28 08:14:13 +00:00
akr
a4fa54a10a
* ext/socket: use rsock_ prefix for internal initialization functions.
...
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@27018 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2010-03-22 16:15:21 +00:00
nobu
4dfd71005c
* ext/socket/socket.c: turn on do_not_reverse_lookup by default,
...
which has been reverted in r9880 probably unintentionally,
according to matz. [ruby-core:24530]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@26541 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2010-02-02 09:15:19 +00:00
usa
e4d1745717
* ext/socket/init.c (rsock_init_sock): mswin doesn't have S_IFSOCK
...
flag in st_mode of struct stat. so, use rb_w32_issocket() function
instead of S_ISSOCK macro.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@25339 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2009-10-15 00:29:10 +00:00
akr
05eb304947
* ext/socket/init.c (rsock_init_sock): validate file descriptor.
...
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@25336 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2009-10-14 15:26:40 +00:00
akr
c7550e2a3d
* ext/socket/init.c (rsock_getfamily): return AF_UNSPEC if getsockname
...
is failed. [ruby-core:24383]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@24160 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2009-07-17 04:38:27 +00:00
akr
c4049f4cb6
* io.c (rb_mWaitReadable): defined.
...
(rb_mWaitWritable): defined.
(io_getpartial): extend IO::WaitReadable on EWOULDBLOCK and EAGAIN.
(rb_io_write_nonblock): extend IO::WaitWritable on EWOULDBLOCK and
EAGAIN.
* error.c (make_errno_exc): extracted from rb_sys_fail.
(rb_mod_sys_fail): new function.
* include/ruby/ruby.h (rb_mod_sys_fail): declared.
(rb_mWaitReadable): declared.
(rb_mWaitWritable): declared.
* ext/socket/init.c (rsock_s_recvfrom_nonblock): extend
IO::WaitReadable on EWOULDBLOCK and EAGAIN.
(rsock_s_accept_nonblock): extend IO::WaitReadable on EWOULDBLOCK,
EAGAIN, ECONNABORTED and EPROTO.
* ext/socket/socket.c (sock_connect_nonblock): extend IO::WaitWritable
on EINPROGRESS.
* ext/socket/ancdata.c (bsock_sendmsg_internal): extend
IO::WaitWritable on EWOULDBLOCK and EAGAIN.
(bsock_recvmsg_internal): extend IO::WaitReadable on EWOULDBLOCK and
EAGAIN.
* ext/openssl/ossl_ssl.c (ossl_ssl_read_internal): raise SSLError
extended by IO::WaitReadable/IO::WaitWritable on
SSL_ERROR_WANT_READ/SSL_ERROR_WANT_WRITE.
* ext/openssl/ossl.c (ossl_make_error): extracted from ossl_raise.
(ossl_exc_new): new function.
* ext/openssl/ossl.h (ossl_exc_new): declared.
* lib/net/protocol.rb (rbuf_fill): rescue IO::WaitReadable and
IO::WaitWritable.
[ruby-core:22539], [ruby-dev:38140]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@23006 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2009-03-19 11:40:38 +00:00
akr
7d1e856766
* ext/socket/init.c (wait_connectable0): remove unreachable code.
...
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@22936 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2009-03-13 14:04:05 +00:00
akr
aa2b22bba2
* ext/socket/ (rsock_getfamily): renamed from rb_sock_getfamily.
...
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@22696 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2009-03-01 11:58:13 +00:00
akr
172d208789
* ext/socket/ (rsock_make_hostent): renamed from sock_make_hostent.
...
(rsock_addrinfo): renamed from sock_addrinfo.
(rsock_getaddrinfo): renamed from sock_getaddrinfo.
(rsock_socket): renamed from ruby_socket.
(rsock_sock_s_socketpair): renamed from sock_s_socketpair.
(rsock_connect): renamed from ruby_connect.
* ext/socket/socket.c (sock_listen): make it static.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@22686 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2009-03-01 06:48:22 +00:00
akr
c49f05dd79
* ext/socket: add rsock_prefix.
...
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@22684 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2009-03-01 06:30:41 +00:00
akr
22cef963c3
* ext/socket/init.c (s_recvfrom): use rb_io_wait_readable after
...
recvfrom.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@22526 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2009-02-22 10:28:38 +00:00
nobu
0ec57a60af
* ext/socket/init.c (s_recvfrom_nonblock): handles EAGAIN too.
...
* ext/socket/init.c (s_accept_nonblock): ditto, and EPROTO depends
on platforms.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@22504 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2009-02-22 04:38:46 +00:00
akr
9cfe35ad50
* io.c (io_getpartial): error message describes what should be
...
waited after nonblocking error.
(rb_io_write_nonblock): ditto.
* ext/socket/init.c (s_recvfrom_nonblock): ditto.
(s_accept_nonblock): ditto.
* ext/socket/socket.c (sock_connect_nonblock): ditto.
* ext/socket/ancdata.c (bsock_sendmsg_internal): ditto.
(bsock_recvmsg_internal): ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@22486 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2009-02-21 15:57:52 +00:00
akr
2ee0859119
* ext/socket/init.c (struct recvfrom_arg): use struct
...
sockaddr_storage.
(recvfrom_blocking): follow struct recvfrom_arg change.
(s_recvfrom): ditto.
(s_recvfrom_nonblock): use struct sockaddr_storage.
* ext/socket/socket.c (sock_accept): use struct sockaddr_storage.
(sock_accept_nonblock): ditto.
(sock_sysaccept): ditto.
* ext/socket/ancdata.c (bsock_recvmsg_internal): use struct
sockaddr_storage.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@22214 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2009-02-10 14:46:51 +00:00
akr
f5da7031b9
* ext/socket/rubysocket.h (level_arg): add family argument.
...
(optname_arg): ditto.
(cmsg_type_arg): ditto.
(rb_sock_getfamily): declared.
* ext/socket/constants.c (level_arg): add family argument.
(optname_arg): ditto.
(cmsg_type_arg): ditto.
* ext/socket/init.c (rb_sock_getfamily): defined.
* ext/socket/option.c (sockopt_initialize): give family for level_arg
and optname_arg.
(sockopt_s_int): ditto.
* ext/socket/basicsocket.c (bsock_setsockopt): ditto.
(bsock_getsockopt): ditto.
* ext/socket/ancdata.c (ancillary_initialize): ditto.
(ancillary_s_int): ditto.
(ancillary_cmsg_is_p): ditto.
(bsock_sendmsg_internal): ditto.
(bsock_recvmsg_internal): use rb_sock_getfamily.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@22184 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2009-02-09 13:56:43 +00:00
akr
88f04bdd32
* ext/socket: AddrInfo is renamed to Addrinfo. [ruby-dev:37876]
...
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@22077 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2009-02-05 11:01:43 +00:00
akr
61fc0c6cf4
* ext/socket/rubysocket.h (cmsg_type_arg): declared.
...
(Init_ancdata): ditto.
* ext/socket/init.c (Init_socket_init): call Init_ancdata.
* ext/socket/constants.c (cmsg_type_arg): defined.
* ext/socket/depend: add dependency for ancdata.o.
* ext/socket/mkconstants.rb: generate scm_optname_to_int.
more constants.
* ext/socket/extconf.rb: add ancdata.o.
* ext/socket/ancdata.c: new file. new method
BasicSocket#{sendmsg,sendmsg_nonblock,recvmsg,recvmsg_nonblock}
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@21943 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2009-02-02 02:51:02 +00:00
akr
ef9206bbea
* ext/socket/rubysocket.h (rb_cSockOpt): declared.
...
(sockopt_new): ditto.
(Init_sockopt): ditto.
* ext/socket/init.c (Init_socket_init): call Init_sockopt.
* ext/socket/depend: add dependency for option.o
* ext/socket/mkconstants.rb: generate intern_level, intern_so_optname,
intern_ip_optname, intern_ipv6_optname, intern_tcp_optname,
intern_udp_optname and intern_scm_optname.
* ext/socket/extconf.rb: add option.o.
* ext/socket/basicsocket.c (bsock_setsockopt): accept Socket::Option
object.
(bsock_getsockopt): return Socket::Option object.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@21936 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2009-02-02 01:53:02 +00:00
akr
2d958b7fb0
* ext/socket/init.c (socks_connect_blocking): moved from
...
sockssocket.c. [ruby-dev:37834]
* sockssocket.c (socks_init): don't omit "int" type.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@21804 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2009-01-27 11:07:41 +00:00
akr
97cbab78dc
* ext/socket: split files for each class.
...
* ext/socket/rubysocket.h: common header.
* ext/socket/basicsocket.c: new file for BasicSocket.
* ext/socket/ipsocket.c: new file for IPSocket.
* ext/socket/tcpsocket.c: new file for TCPSocket.
* ext/socket/tcpserver.c: new file for TCPServer.
* ext/socket/sockssocket.c: new file for SOCKSSocket.
* ext/socket/udpsocket.c: new file for UDPSocket.
* ext/socket/unixsocket.c: new file for UNIXSocket.
* ext/socket/unixserver.c: new file for UNIXServer.
* ext/socket/socket.c: now for Socket.
* ext/socket/raddrinfo.c: new file for AddrInfo and name resolution.
* ext/socket/constants.c: new file for constants.
* ext/socket/init.c: new file for utilities.
* ext/socket/mkconstants.rb: export *_to_int.
* ext/socket/extconf.rb: add new object files.
* ext/socket/depend: add dependencies for new files.
* ext/.document: add new files.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@21619 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2009-01-17 04:11:27 +00:00