eventmachine 0.12.8 → 0.12.10

Sign up to get free protection for your applications and to get access to all the features.
Files changed (66) hide show
  1. data/.gitignore +2 -1
  2. data/Rakefile +155 -45
  3. data/eventmachine.gemspec +4 -5
  4. data/ext/binder.cpp +13 -14
  5. data/ext/binder.h +5 -7
  6. data/ext/cmain.cpp +184 -42
  7. data/ext/cplusplus.cpp +20 -20
  8. data/ext/ed.cpp +242 -81
  9. data/ext/ed.h +39 -22
  10. data/ext/em.cpp +127 -108
  11. data/ext/em.h +27 -18
  12. data/ext/emwin.cpp +3 -3
  13. data/ext/eventmachine.h +49 -38
  14. data/ext/eventmachine_cpp.h +4 -4
  15. data/ext/extconf.rb +28 -13
  16. data/ext/fastfilereader/extconf.rb +11 -5
  17. data/ext/project.h +12 -1
  18. data/ext/rubymain.cpp +222 -103
  19. data/ext/ssl.cpp +3 -3
  20. data/ext/ssl.h +2 -2
  21. data/java/src/com/rubyeventmachine/EmReactor.java +396 -249
  22. data/java/src/com/rubyeventmachine/EventableChannel.java +16 -4
  23. data/java/src/com/rubyeventmachine/EventableDatagramChannel.java +23 -5
  24. data/java/src/com/rubyeventmachine/EventableSocketChannel.java +181 -61
  25. data/java/src/com/rubyeventmachine/{Application.java → application/Application.java} +25 -31
  26. data/java/src/com/rubyeventmachine/{Connection.java → application/Connection.java} +2 -2
  27. data/java/src/com/rubyeventmachine/{ConnectionFactory.java → application/ConnectionFactory.java} +1 -1
  28. data/java/src/com/rubyeventmachine/{DefaultConnectionFactory.java → application/DefaultConnectionFactory.java} +2 -2
  29. data/java/src/com/rubyeventmachine/{PeriodicTimer.java → application/PeriodicTimer.java} +1 -1
  30. data/java/src/com/rubyeventmachine/{Timer.java → application/Timer.java} +1 -1
  31. data/java/src/com/rubyeventmachine/tests/ApplicationTest.java +1 -0
  32. data/java/src/com/rubyeventmachine/tests/ConnectTest.java +4 -2
  33. data/java/src/com/rubyeventmachine/tests/TestDatagrams.java +1 -1
  34. data/java/src/com/rubyeventmachine/tests/TestServers.java +1 -0
  35. data/java/src/com/rubyeventmachine/tests/TestTimers.java +1 -0
  36. data/lib/em/connection.rb +71 -12
  37. data/lib/em/deferrable.rb +5 -0
  38. data/lib/em/protocols.rb +1 -0
  39. data/lib/em/protocols/httpclient2.rb +8 -0
  40. data/lib/em/protocols/line_and_text.rb +0 -1
  41. data/lib/em/protocols/linetext2.rb +1 -0
  42. data/lib/em/protocols/object_protocol.rb +8 -2
  43. data/lib/em/protocols/smtpclient.rb +42 -16
  44. data/lib/em/protocols/socks4.rb +66 -0
  45. data/lib/em/queue.rb +1 -1
  46. data/lib/em/timers.rb +2 -1
  47. data/lib/em/version.rb +1 -1
  48. data/lib/eventmachine.rb +125 -169
  49. data/lib/jeventmachine.rb +124 -9
  50. data/tasks/{cpp.rake → cpp.rake_example} +0 -0
  51. data/tests/test_attach.rb +29 -4
  52. data/tests/test_basic.rb +1 -2
  53. data/tests/test_connection_count.rb +10 -20
  54. data/tests/test_epoll.rb +0 -2
  55. data/tests/test_get_sock_opt.rb +30 -0
  56. data/tests/test_httpclient2.rb +3 -3
  57. data/tests/test_inactivity_timeout.rb +21 -1
  58. data/tests/test_ltp.rb +0 -6
  59. data/tests/test_next_tick.rb +0 -2
  60. data/tests/test_pause.rb +70 -0
  61. data/tests/test_pending_connect_timeout.rb +48 -0
  62. data/tests/test_ssl_args.rb +16 -5
  63. data/tests/test_timers.rb +22 -1
  64. metadata +14 -12
  65. data/tasks/project.rake +0 -79
  66. data/tasks/tests.rake +0 -193
data/ext/em.h CHANGED
@@ -34,8 +34,16 @@ See the file COPYING for complete licensing information.
34
34
  #include <ruby.h>
35
35
  #define EmSelect rb_thread_select
36
36
 
37
- #ifdef HAVE_RBTRAP
37
+ #if defined(HAVE_RBTRAP)
38
38
  #include <rubysig.h>
39
+ #elif defined(HAVE_RB_THREAD_CHECK_INTS)
40
+ extern "C" {
41
+ void rb_enable_interrupt(void);
42
+ void rb_disable_interrupt(void);
43
+ }
44
+
45
+ #define TRAP_BEG rb_enable_interrupt()
46
+ #define TRAP_END do { rb_disable_interrupt(); rb_thread_check_ints(); } while(0)
39
47
  #else
40
48
  #define TRAP_BEG
41
49
  #define TRAP_END
@@ -74,28 +82,28 @@ class EventMachine_t
74
82
  static void SetMaxTimerCount (int);
75
83
 
76
84
  public:
77
- EventMachine_t (void(*event_callback)(const char*, int, const char*, int));
85
+ EventMachine_t (void(*event_callback)(const unsigned long, int, const char*, const unsigned long));
78
86
  virtual ~EventMachine_t();
79
87
 
80
88
  void Run();
81
89
  void ScheduleHalt();
82
90
  void SignalLoopBreaker();
83
- const char *InstallOneshotTimer (int);
84
- const char *ConnectToServer (const char *, int, const char *, int);
85
- const char *ConnectToUnixServer (const char *);
86
-
87
- const char *CreateTcpServer (const char *, int);
88
- const char *OpenDatagramSocket (const char *, int);
89
- const char *CreateUnixDomainServer (const char*);
90
- const char *_OpenFileForWriting (const char*);
91
- const char *OpenKeyboard();
91
+ const unsigned long InstallOneshotTimer (int);
92
+ const unsigned long ConnectToServer (const char *, int, const char *, int);
93
+ const unsigned long ConnectToUnixServer (const char *);
94
+
95
+ const unsigned long CreateTcpServer (const char *, int);
96
+ const unsigned long OpenDatagramSocket (const char *, int);
97
+ const unsigned long CreateUnixDomainServer (const char*);
98
+ const unsigned long _OpenFileForWriting (const char*);
99
+ const unsigned long OpenKeyboard();
92
100
  //const char *Popen (const char*, const char*);
93
- const char *Socketpair (char* const*);
101
+ const unsigned long Socketpair (char* const*);
94
102
 
95
103
  void Add (EventableDescriptor*);
96
104
  void Modify (EventableDescriptor*);
97
105
 
98
- const char *AttachFD (int, bool, bool);
106
+ const unsigned long AttachFD (int, bool);
99
107
  int DetachFD (EventableDescriptor*);
100
108
 
101
109
  void ArmKqueueWriter (EventableDescriptor*);
@@ -112,18 +120,18 @@ class EventMachine_t
112
120
  float GetHeartbeatInterval();
113
121
  int SetHeartbeatInterval(float);
114
122
 
115
- const char *WatchFile (const char*);
123
+ const unsigned long WatchFile (const char*);
116
124
  void UnwatchFile (int);
117
- void UnwatchFile (const char*);
125
+ void UnwatchFile (const unsigned long);
118
126
 
119
127
  #ifdef HAVE_KQUEUE
120
128
  void _HandleKqueueFileEvent (struct kevent*);
121
129
  void _RegisterKqueueFileEvent(int);
122
130
  #endif
123
131
 
124
- const char *WatchPid (int);
132
+ const unsigned long WatchPid (int);
125
133
  void UnwatchPid (int);
126
- void UnwatchPid (const char *);
134
+ void UnwatchPid (const unsigned long);
127
135
 
128
136
  #ifdef HAVE_KQUEUE
129
137
  void _HandleKqueuePidEvent (struct kevent*);
@@ -160,7 +168,7 @@ class EventMachine_t
160
168
  MaxEvents = 4096
161
169
  };
162
170
  int HeartbeatInterval;
163
- void (*EventCallback)(const char*, int, const char*, int);
171
+ void (*EventCallback)(const unsigned long, int, const char*, const unsigned long);
164
172
 
165
173
  class Timer_t: public Bindable_t {
166
174
  };
@@ -212,6 +220,7 @@ struct SelectData_t
212
220
  int maxsocket;
213
221
  fd_set fdreads;
214
222
  fd_set fdwrites;
223
+ fd_set fderrors;
215
224
  timeval tv;
216
225
  int nSockets;
217
226
  };
@@ -138,7 +138,7 @@ bool EventMachine_t::_RunTimers()
138
138
  if (i->first > gCurrentLoopTime)
139
139
  break;
140
140
  if (EventCallback)
141
- (*EventCallback) ("", EM_TIMER_FIRED, i->second.GetBinding().c_str(), i->second.GetBinding().length());
141
+ (*EventCallback) (NULL, EM_TIMER_FIRED, NULL, i->second.GetBinding());
142
142
  Timers.erase (i);
143
143
  }
144
144
  return true;
@@ -158,7 +158,7 @@ const char *EventMachine_t::InstallOneshotTimer (int seconds)
158
158
 
159
159
  Timer_t t;
160
160
  Timers.insert (make_pair (time(NULL) + seconds, t));
161
- return t.GetBinding().c_str();
161
+ return t.GetBinding();
162
162
  }
163
163
 
164
164
 
@@ -230,7 +230,7 @@ const char *EventMachine_t::CreateTcpServer (const char *server, int port)
230
230
  if (!ad)
231
231
  throw std::runtime_error ("unable to allocate acceptor");
232
232
  Add (ad);
233
- output_binding = ad->GetBinding().c_str();
233
+ output_binding = ad->GetBinding();
234
234
 
235
235
  CreateIoCompletionPort ((HANDLE)sd_accept, Iocp, NULL, 0);
236
236
  SOCKET sd = socket (AF_INET, SOCK_STREAM, 0);
@@ -39,43 +39,54 @@ extern "C" {
39
39
 
40
40
  };
41
41
 
42
- void evma_initialize_library (void(*)(const char*, int, const char*, int));
42
+ void evma_initialize_library (void(*)(const unsigned long, int, const char*, const unsigned long));
43
43
  void evma_run_machine();
44
44
  void evma_release_library();
45
- const char *evma_install_oneshot_timer (int seconds);
46
- const char *evma_connect_to_server (const char *bind_addr, int bind_port, const char *server, int port);
47
- const char *evma_connect_to_unix_server (const char *server);
48
-
49
- const char *evma_attach_fd (int file_descriptor, int read_mode, int write_mode);
50
- int evma_detach_fd (const char *binding);
51
-
52
- void evma_stop_tcp_server (const char *signature);
53
- const char *evma_create_tcp_server (const char *address, int port);
54
- const char *evma_create_unix_domain_server (const char *filename);
55
- const char *evma_open_datagram_socket (const char *server, int port);
56
- const char *evma_open_keyboard();
57
- void evma_set_tls_parms (const char *binding, const char *privatekey_filename, const char *certchain_filenane, int verify_peer);
58
- void evma_start_tls (const char *binding);
45
+ const unsigned long evma_install_oneshot_timer (int seconds);
46
+ const unsigned long evma_connect_to_server (const char *bind_addr, int bind_port, const char *server, int port);
47
+ const unsigned long evma_connect_to_unix_server (const char *server);
48
+
49
+ const unsigned long evma_attach_fd (int file_descriptor, int watch_mode);
50
+ int evma_detach_fd (const unsigned long binding);
51
+ int evma_get_file_descriptor (const unsigned long binding);
52
+ int evma_is_notify_readable (const unsigned long binding);
53
+ void evma_set_notify_readable (const unsigned long binding, int mode);
54
+ int evma_is_notify_writable (const unsigned long binding);
55
+ void evma_set_notify_writable (const unsigned long binding, int mode);
56
+
57
+ int evma_pause(const unsigned long binding);
58
+ int evma_is_paused(const unsigned long binding);
59
+ int evma_resume(const unsigned long binding);
60
+
61
+ void evma_stop_tcp_server (const unsigned long signature);
62
+ const unsigned long evma_create_tcp_server (const char *address, int port);
63
+ const unsigned long evma_create_unix_domain_server (const char *filename);
64
+ const unsigned long evma_open_datagram_socket (const char *server, int port);
65
+ const unsigned long evma_open_keyboard();
66
+ void evma_set_tls_parms (const unsigned long binding, const char *privatekey_filename, const char *certchain_filenane, int verify_peer);
67
+ void evma_start_tls (const unsigned long binding);
59
68
 
60
69
  #ifdef WITH_SSL
61
- X509 *evma_get_peer_cert (const char *binding);
62
- void evma_accept_ssl_peer (const char *binding);
70
+ X509 *evma_get_peer_cert (const unsigned long binding);
71
+ void evma_accept_ssl_peer (const unsigned long binding);
63
72
  #endif
64
73
 
65
- int evma_get_peername (const char *binding, struct sockaddr*);
66
- int evma_get_sockname (const char *binding, struct sockaddr*);
67
- int evma_get_subprocess_pid (const char *binding, pid_t*);
68
- int evma_get_subprocess_status (const char *binding, int*);
74
+ int evma_get_peername (const unsigned long binding, struct sockaddr*);
75
+ int evma_get_sockname (const unsigned long binding, struct sockaddr*);
76
+ int evma_get_subprocess_pid (const unsigned long binding, pid_t*);
77
+ int evma_get_subprocess_status (const unsigned long binding, int*);
69
78
  int evma_get_connection_count();
70
- int evma_send_data_to_connection (const char *binding, const char *data, int data_length);
71
- int evma_send_datagram (const char *binding, const char *data, int data_length, const char *address, int port);
72
- float evma_get_comm_inactivity_timeout (const char *binding);
73
- int evma_set_comm_inactivity_timeout (const char *binding, float value);
74
- int evma_get_outbound_data_size (const char *binding);
75
- int evma_send_file_data_to_connection (const char *binding, const char *filename);
76
-
77
- void evma_close_connection (const char *binding, int after_writing);
78
- int evma_report_connection_error_status (const char *binding);
79
+ int evma_send_data_to_connection (const unsigned long binding, const char *data, int data_length);
80
+ int evma_send_datagram (const unsigned long binding, const char *data, int data_length, const char *address, int port);
81
+ float evma_get_comm_inactivity_timeout (const unsigned long binding);
82
+ int evma_set_comm_inactivity_timeout (const unsigned long binding, float value);
83
+ float evma_get_pending_connect_timeout (const unsigned long binding);
84
+ int evma_set_pending_connect_timeout (const unsigned long binding, float value);
85
+ int evma_get_outbound_data_size (const unsigned long binding);
86
+ int evma_send_file_data_to_connection (const unsigned long binding, const char *filename);
87
+
88
+ void evma_close_connection (const unsigned long binding, int after_writing);
89
+ int evma_report_connection_error_status (const unsigned long binding);
79
90
  void evma_signal_loopbreak();
80
91
  void evma_set_timer_quantum (int);
81
92
  int evma_get_max_timer_count();
@@ -85,17 +96,17 @@ extern "C" {
85
96
  float evma_get_heartbeat_interval();
86
97
  int evma_set_heartbeat_interval(float);
87
98
 
88
- const char *evma__write_file (const char *filename);
89
- const char *evma_popen (char * const*cmd_strings);
99
+ const unsigned long evma__write_file (const char *filename);
100
+ const unsigned long evma_popen (char * const*cmd_strings);
90
101
 
91
- const char *evma_watch_filename (const char *fname);
92
- void evma_unwatch_filename (const char *sig);
102
+ const unsigned long evma_watch_filename (const char *fname);
103
+ void evma_unwatch_filename (const unsigned long);
93
104
 
94
- const char *evma_watch_pid (int);
95
- void evma_unwatch_pid (const char *sig);
105
+ const unsigned long evma_watch_pid (int);
106
+ void evma_unwatch_pid (const unsigned long);
96
107
 
97
- void evma_start_proxy(const char*, const char*);
98
- void evma_stop_proxy(const char*);
108
+ void evma_start_proxy(const unsigned long, const unsigned long, const unsigned long);
109
+ void evma_stop_proxy(const unsigned long);
99
110
 
100
111
  int evma_set_rlimit_nofile (int n_files);
101
112
 
@@ -26,7 +26,7 @@ See the file COPYING for complete licensing information.
26
26
 
27
27
  namespace EM {
28
28
 
29
- void Callback (const char *sig, int event, const char *data, int length);
29
+ void Callback (const unsigned long sig, int event, const char *data, const unsigned long length);
30
30
  void Run (void(*)(void));
31
31
  void AddTimer (int, void(*)());
32
32
  void StopReactor();
@@ -40,12 +40,12 @@ namespace EM {
40
40
  Eventable() {}
41
41
  virtual ~Eventable() {}
42
42
 
43
- std::string Signature;
43
+ unsigned long Signature;
44
44
 
45
45
  // Called by the framework
46
46
  virtual void ReceiveData (const char *data, int length) {}
47
47
  virtual void ConnectionCompleted() {}
48
- virtual void Accept (const char*) {}
48
+ virtual void Accept (const unsigned long) {}
49
49
  virtual void Unbind() {}
50
50
  virtual void PostInit() {}
51
51
  virtual void SslHandshakeCompleted() {}
@@ -81,7 +81,7 @@ namespace EM {
81
81
  virtual ~Acceptor() {}
82
82
 
83
83
  void Start (const char*, int);
84
- void Accept (const char*);
84
+ void Accept (const unsigned long);
85
85
 
86
86
  virtual Connection *MakeConnection() {return new Connection();}
87
87
  };
@@ -18,6 +18,8 @@ add_define "HAVE_TBR" if have_func('rb_thread_blocking_region')# and have_macro(
18
18
  add_define "HAVE_INOTIFY" if inotify = have_func('inotify_init', 'sys/inotify.h')
19
19
  add_define "HAVE_OLD_INOTIFY" if !inotify && have_macro('__NR_inotify_init', 'sys/syscall.h')
20
20
  add_define 'HAVE_WRITEV' if have_func('writev', 'sys/uio.h')
21
+ have_func('rb_thread_check_ints')
22
+ have_func('rb_time_new')
21
23
 
22
24
  # Minor platform details between *nix and Windows:
23
25
 
@@ -48,9 +50,8 @@ when /mswin32/, /mingw32/, /bccwin32/
48
50
  end
49
51
 
50
52
  when /solaris/
51
- check_libs(%w[nsl socket], true)
52
-
53
53
  add_define 'OS_SOLARIS8'
54
+ check_libs(%w[nsl socket], true)
54
55
 
55
56
  # Patch by Tim Pease, fixes SUNWspro compile problems.
56
57
  if CONFIG['CC'] == 'cc'
@@ -67,31 +68,36 @@ when /openbsd/
67
68
  # OpenBSD branch contributed by Guillaume Sellier.
68
69
 
69
70
  # on Unix we need a g++ link, not gcc. On OpenBSD, linking against libstdc++ have to be explicitly done for shared libs
70
- CONFIG['LDSHARED'] = "$(CXX) -shared -lstdc++"
71
+ CONFIG['LDSHARED'] = "$(CXX) -shared -lstdc++ -fPIC"
72
+ CONFIG['LDSHAREDXX'] = "$(CXX) -shared -lstdc++ -fPIC"
71
73
 
72
74
  when /darwin/
73
-
74
75
  # on Unix we need a g++ link, not gcc.
75
76
  # Ff line contributed by Daniel Harple.
76
77
  CONFIG['LDSHARED'] = "$(CXX) " + CONFIG['LDSHARED'].split[1..-1].join(' ')
77
78
 
78
79
  when /linux/
80
+ add_define 'HAVE_EPOLL' if have_func('epoll_create', 'sys/epoll.h')
79
81
 
80
82
  # Original epoll test is inadequate because 2.4 kernels have the header
81
83
  # but not the code.
82
84
  # add_define 'HAVE_EPOLL' if have_header('sys/epoll.h')
83
- if have_header('sys/epoll.h')
84
- File.open("hasEpollTest.c", "w") {|f|
85
- f.puts "#include <sys/epoll.h>"
86
- f.puts "int main() { epoll_create(1024); return 0;}"
87
- }
88
- (e = system( "gcc hasEpollTest.c -o hasEpollTest " )) and (e = $?.to_i)
89
- `rm -f hasEpollTest.c hasEpollTest`
90
- add_define 'HAVE_EPOLL' if e == 0
91
- end
85
+ # if have_header('sys/epoll.h')
86
+ # File.open("hasEpollTest.c", "w") {|f|
87
+ # f.puts "#include <sys/epoll.h>"
88
+ # f.puts "int main() { epoll_create(1024); return 0;}"
89
+ # }
90
+ # (e = system( "gcc hasEpollTest.c -o hasEpollTest " )) and (e = $?.to_i)
91
+ # `rm -f hasEpollTest.c hasEpollTest`
92
+ # add_define 'HAVE_EPOLL' if e == 0
93
+ # end
92
94
 
93
95
  # on Unix we need a g++ link, not gcc.
94
96
  CONFIG['LDSHARED'] = "$(CXX) -shared"
97
+
98
+ when /aix/
99
+ CONFIG['LDSHARED'] = "$(CXX) -shared -Wl,-G -Wl,-brtl"
100
+
95
101
  else
96
102
  # on Unix we need a g++ link, not gcc.
97
103
  CONFIG['LDSHARED'] = "$(CXX) -shared"
@@ -130,4 +136,13 @@ else
130
136
  add_define "WITHOUT_SSL"
131
137
  end
132
138
 
139
+ # solaris c++ compiler doesn't have make_pair()
140
+ TRY_LINK.sub!('$(CC)', '$(CXX)')
141
+ add_define 'HAVE_MAKE_PAIR' if try_link(<<SRC, '-lstdc++')
142
+ #include <utility>
143
+ using namespace std;
144
+ int main(){ pair<int,int> tuple = make_pair(1,2); }
145
+ SRC
146
+ TRY_LINK.sub!('$(CXX)', '$(CC)')
147
+
133
148
  create_makefile "rubyeventmachine"
@@ -26,7 +26,7 @@ else
26
26
  add_define 'OS_UNIX'
27
27
  end
28
28
 
29
-
29
+ # Main platform invariances:
30
30
 
31
31
  case RUBY_PLATFORM
32
32
  when /mswin32/, /mingw32/, /bccwin32/
@@ -41,9 +41,8 @@ when /mswin32/, /mingw32/, /bccwin32/
41
41
  end
42
42
 
43
43
  when /solaris/
44
- check_libs(%w[nsl socket], true)
45
-
46
44
  add_define 'OS_SOLARIS8'
45
+ check_libs(%w[nsl socket], true)
47
46
 
48
47
  # Patch by Tim Pease, fixes SUNWspro compile problems.
49
48
  if CONFIG['CC'] == 'cc'
@@ -55,20 +54,27 @@ when /solaris/
55
54
  # on Unix we need a g++ link, not gcc.
56
55
  CONFIG['LDSHARED'] = "$(CXX) -shared"
57
56
  end
57
+
58
58
  when /openbsd/
59
59
  # OpenBSD branch contributed by Guillaume Sellier.
60
60
 
61
61
  # on Unix we need a g++ link, not gcc. On OpenBSD, linking against libstdc++ have to be explicitly done for shared libs
62
- CONFIG['LDSHARED'] = "$(CXX) -shared -lstdc++"
62
+ CONFIG['LDSHARED'] = "$(CXX) -shared -lstdc++ -fPIC"
63
+ CONFIG['LDSHAREDXX'] = "$(CXX) -shared -lstdc++ -fPIC"
64
+
63
65
  when /darwin/
64
66
  # on Unix we need a g++ link, not gcc.
65
67
  # Ff line contributed by Daniel Harple.
66
68
  CONFIG['LDSHARED'] = "$(CXX) " + CONFIG['LDSHARED'].split[1..-1].join(' ')
67
69
 
68
70
  when /linux/
69
-
70
71
  # on Unix we need a g++ link, not gcc.
71
72
  CONFIG['LDSHARED'] = "$(CXX) -shared"
73
+
74
+ when /aix/
75
+ # on Unix we need a g++ link, not gcc.
76
+ CONFIG['LDSHARED'] = "$(CXX) -shared -Wl,-G"
77
+
72
78
  else
73
79
  # on Unix we need a g++ link, not gcc.
74
80
  CONFIG['LDSHARED'] = "$(CXX) -shared"
@@ -69,11 +69,21 @@ typedef int SOCKET;
69
69
  #ifndef INADDR_NONE
70
70
  #define INADDR_NONE ((unsigned long)-1)
71
71
  #endif
72
+ #endif /* OS_SOLARIS8 */
73
+
74
+ #ifdef _AIX
75
+ #include <strings.h>
76
+ #ifndef AF_LOCAL
77
+ #define AF_LOCAL AF_UNIX
72
78
  #endif
73
- #endif
79
+ #endif /* _AIX */
74
80
 
81
+ #endif /* OS_UNIX */
75
82
 
76
83
  #ifdef OS_WIN32
84
+ // 21Sep09: windows limits select() to 64 sockets by default, we increase it to 1024 here (before including winsock2.h)
85
+ #define FD_SETSIZE 1024
86
+
77
87
  #define WIN32_LEAN_AND_MEAN
78
88
  #include <windows.h>
79
89
  #include <winsock2.h>
@@ -81,6 +91,7 @@ typedef int SOCKET;
81
91
  #include <rpc.h>
82
92
  #include <fcntl.h>
83
93
  #include <assert.h>
94
+
84
95
  typedef int socklen_t;
85
96
  typedef int pid_t;
86
97
  #endif
@@ -32,8 +32,10 @@ Statics
32
32
  static VALUE EmModule;
33
33
  static VALUE EmConnection;
34
34
 
35
+ static VALUE EM_eConnectionError;
35
36
  static VALUE EM_eUnknownTimerFired;
36
37
  static VALUE EM_eConnectionNotBound;
38
+ static VALUE EM_eUnsupported;
37
39
 
38
40
  static VALUE Intern_at_signature;
39
41
  static VALUE Intern_at_timers;
@@ -53,10 +55,10 @@ static VALUE Intern_proxy_target_unbound;
53
55
  static VALUE rb_cProcStatus;
54
56
 
55
57
  struct em_event {
56
- const char *a1;
58
+ unsigned long a1;
57
59
  int a2;
58
60
  const char *a3;
59
- int a4;
61
+ unsigned long a4;
60
62
  };
61
63
 
62
64
  /****************
@@ -65,30 +67,30 @@ t_event_callback
65
67
 
66
68
  static void event_callback (struct em_event* e)
67
69
  {
68
- const char *a1 = e->a1;
70
+ const unsigned long a1 = e->a1;
69
71
  int a2 = e->a2;
70
72
  const char *a3 = e->a3;
71
- int a4 = e->a4;
73
+ const unsigned long a4 = e->a4;
72
74
 
73
75
  if (a2 == EM_CONNECTION_READ) {
74
76
  VALUE t = rb_ivar_get (EmModule, Intern_at_conns);
75
- VALUE q = rb_hash_aref (t, rb_str_new2(a1));
77
+ VALUE q = rb_hash_aref (t, ULONG2NUM (a1));
76
78
  if (q == Qnil)
77
- rb_raise (EM_eConnectionNotBound, "received %d bytes of data for unknown signature: %s", a4, a1);
79
+ rb_raise (EM_eConnectionNotBound, "received %lu bytes of data for unknown signature: %lu", a4, a1);
78
80
  rb_funcall (q, Intern_receive_data, 1, rb_str_new (a3, a4));
79
81
  }
80
82
  else if (a2 == EM_CONNECTION_NOTIFY_READABLE) {
81
83
  VALUE t = rb_ivar_get (EmModule, Intern_at_conns);
82
- VALUE q = rb_hash_aref (t, rb_str_new2(a1));
84
+ VALUE q = rb_hash_aref (t, ULONG2NUM (a1));
83
85
  if (q == Qnil)
84
- rb_raise (EM_eConnectionNotBound, "unknown connection: %s", a1);
86
+ rb_raise (EM_eConnectionNotBound, "unknown connection: %lu", a1);
85
87
  rb_funcall (q, Intern_notify_readable, 0);
86
88
  }
87
89
  else if (a2 == EM_CONNECTION_NOTIFY_WRITABLE) {
88
90
  VALUE t = rb_ivar_get (EmModule, Intern_at_conns);
89
- VALUE q = rb_hash_aref (t, rb_str_new2(a1));
91
+ VALUE q = rb_hash_aref (t, ULONG2NUM (a1));
90
92
  if (q == Qnil)
91
- rb_raise (EM_eConnectionNotBound, "unknown connection: %s", a1);
93
+ rb_raise (EM_eConnectionNotBound, "unknown connection: %lu", a1);
92
94
  rb_funcall (q, Intern_notify_writable, 0);
93
95
  }
94
96
  else if (a2 == EM_LOOPBREAK_SIGNAL) {
@@ -96,9 +98,9 @@ static void event_callback (struct em_event* e)
96
98
  }
97
99
  else if (a2 == EM_TIMER_FIRED) {
98
100
  VALUE t = rb_ivar_get (EmModule, Intern_at_timers);
99
- VALUE q = rb_funcall (t, Intern_delete, 1, rb_str_new(a3, a4));
101
+ VALUE q = rb_funcall (t, Intern_delete, 1, ULONG2NUM (a4));
100
102
  if (q == Qnil) {
101
- rb_raise (EM_eUnknownTimerFired, "no such timer: %s", a1);
103
+ rb_raise (EM_eUnknownTimerFired, "no such timer: %lu", a4);
102
104
  } else if (q == Qfalse) {
103
105
  /* Timer Canceled */
104
106
  } else {
@@ -108,16 +110,16 @@ static void event_callback (struct em_event* e)
108
110
  #ifdef WITH_SSL
109
111
  else if (a2 == EM_SSL_HANDSHAKE_COMPLETED) {
110
112
  VALUE t = rb_ivar_get (EmModule, Intern_at_conns);
111
- VALUE q = rb_hash_aref (t, rb_str_new2(a1));
113
+ VALUE q = rb_hash_aref (t, ULONG2NUM (a1));
112
114
  if (q == Qnil)
113
- rb_raise (EM_eConnectionNotBound, "unknown connection: %s", a1);
115
+ rb_raise (EM_eConnectionNotBound, "unknown connection: %lu", a1);
114
116
  rb_funcall (q, Intern_ssl_handshake_completed, 0);
115
117
  }
116
118
  else if (a2 == EM_SSL_VERIFY) {
117
119
  VALUE t = rb_ivar_get (EmModule, Intern_at_conns);
118
- VALUE q = rb_hash_aref (t, rb_str_new2(a1));
120
+ VALUE q = rb_hash_aref (t, ULONG2NUM (a1));
119
121
  if (q == Qnil)
120
- rb_raise (EM_eConnectionNotBound, "unknown connection: %s", a1);
122
+ rb_raise (EM_eConnectionNotBound, "unknown connection: %lu", a1);
121
123
  VALUE r = rb_funcall (q, Intern_ssl_verify_peer, 1, rb_str_new(a3, a4));
122
124
  if (RTEST(r))
123
125
  evma_accept_ssl_peer (a1);
@@ -125,13 +127,13 @@ static void event_callback (struct em_event* e)
125
127
  #endif
126
128
  else if (a2 == EM_PROXY_TARGET_UNBOUND) {
127
129
  VALUE t = rb_ivar_get (EmModule, Intern_at_conns);
128
- VALUE q = rb_hash_aref (t, rb_str_new2(a1));
130
+ VALUE q = rb_hash_aref (t, ULONG2NUM (a1));
129
131
  if (q == Qnil)
130
- rb_raise (EM_eConnectionNotBound, "unknown connection: %s", a1);
132
+ rb_raise (EM_eConnectionNotBound, "unknown connection: %lu", a1);
131
133
  rb_funcall (q, Intern_proxy_target_unbound, 0);
132
134
  }
133
135
  else
134
- rb_funcall (EmModule, Intern_event_callback, 3, rb_str_new2(a1), (a2 << 1) | 1, rb_str_new(a3,a4));
136
+ rb_funcall (EmModule, Intern_event_callback, 3, ULONG2NUM(a1), INT2FIX(a2), a3 ? rb_str_new(a3,a4) : ULONG2NUM(a4));
135
137
  }
136
138
 
137
139
  /*******************
@@ -148,7 +150,7 @@ static void event_error_handler(VALUE unused, VALUE err)
148
150
  event_callback_wrapper
149
151
  **********************/
150
152
 
151
- static void event_callback_wrapper (const char *a1, int a2, const char *a3, int a4)
153
+ static void event_callback_wrapper (const unsigned long a1, int a2, const char *a3, const unsigned long a4)
152
154
  {
153
155
  struct em_event e;
154
156
  e.a1 = a1;
@@ -191,10 +193,10 @@ t_add_oneshot_timer
191
193
 
192
194
  static VALUE t_add_oneshot_timer (VALUE self, VALUE interval)
193
195
  {
194
- const char *f = evma_install_oneshot_timer (FIX2INT (interval));
195
- if (!f || !*f)
196
- rb_raise (rb_eRuntimeError, "no timer");
197
- return rb_str_new2 (f);
196
+ const unsigned long f = evma_install_oneshot_timer (FIX2INT (interval));
197
+ if (!f)
198
+ rb_raise (rb_eRuntimeError, "ran out of timers; use #set_max_timers to increase limit");
199
+ return ULONG2NUM (f);
198
200
  }
199
201
 
200
202
 
@@ -204,10 +206,10 @@ t_start_server
204
206
 
205
207
  static VALUE t_start_server (VALUE self, VALUE server, VALUE port)
206
208
  {
207
- const char *f = evma_create_tcp_server (StringValuePtr(server), FIX2INT(port));
208
- if (!f || !*f)
209
+ const unsigned long f = evma_create_tcp_server (StringValuePtr(server), FIX2INT(port));
210
+ if (!f)
209
211
  rb_raise (rb_eRuntimeError, "no acceptor");
210
- return rb_str_new2 (f);
212
+ return ULONG2NUM (f);
211
213
  }
212
214
 
213
215
  /*************
@@ -216,7 +218,7 @@ t_stop_server
216
218
 
217
219
  static VALUE t_stop_server (VALUE self, VALUE signature)
218
220
  {
219
- evma_stop_tcp_server (StringValuePtr (signature));
221
+ evma_stop_tcp_server (NUM2ULONG (signature));
220
222
  return Qnil;
221
223
  }
222
224
 
@@ -227,10 +229,10 @@ t_start_unix_server
227
229
 
228
230
  static VALUE t_start_unix_server (VALUE self, VALUE filename)
229
231
  {
230
- const char *f = evma_create_unix_domain_server (StringValuePtr(filename));
231
- if (!f || !*f)
232
+ const unsigned long f = evma_create_unix_domain_server (StringValuePtr(filename));
233
+ if (!f)
232
234
  rb_raise (rb_eRuntimeError, "no unix-domain acceptor");
233
- return rb_str_new2 (f);
235
+ return ULONG2NUM (f);
234
236
  }
235
237
 
236
238
 
@@ -241,7 +243,7 @@ t_send_data
241
243
 
242
244
  static VALUE t_send_data (VALUE self, VALUE signature, VALUE data, VALUE data_length)
243
245
  {
244
- int b = evma_send_data_to_connection (StringValuePtr (signature), StringValuePtr (data), FIX2INT (data_length));
246
+ int b = evma_send_data_to_connection (NUM2ULONG (signature), StringValuePtr (data), FIX2INT (data_length));
245
247
  return INT2NUM (b);
246
248
  }
247
249
 
@@ -252,7 +254,7 @@ t_start_tls
252
254
 
253
255
  static VALUE t_start_tls (VALUE self, VALUE signature)
254
256
  {
255
- evma_start_tls (StringValuePtr (signature));
257
+ evma_start_tls (NUM2ULONG (signature));
256
258
  return Qnil;
257
259
  }
258
260
 
@@ -267,7 +269,7 @@ static VALUE t_set_tls_parms (VALUE self, VALUE signature, VALUE privkeyfile, VA
267
269
  * It's expected that the parameter list will grow as we add more supported features.
268
270
  * ALL of these parameters are optional, and can be specified as empty or NULL strings.
269
271
  */
270
- evma_set_tls_parms (StringValuePtr (signature), StringValuePtr (privkeyfile), StringValuePtr (certchainfile), (verify_peer == Qtrue ? 1 : 0));
272
+ evma_set_tls_parms (NUM2ULONG (signature), StringValuePtr (privkeyfile), StringValuePtr (certchainfile), (verify_peer == Qtrue ? 1 : 0));
271
273
  return Qnil;
272
274
  }
273
275
 
@@ -284,7 +286,7 @@ static VALUE t_get_peer_cert (VALUE self, VALUE signature)
284
286
  BUF_MEM *buf;
285
287
  BIO *out;
286
288
 
287
- cert = evma_get_peer_cert (StringValuePtr (signature));
289
+ cert = evma_get_peer_cert (NUM2ULONG (signature));
288
290
 
289
291
  if (cert != NULL) {
290
292
  out = BIO_new(BIO_s_mem());
@@ -306,7 +308,7 @@ t_get_peername
306
308
  static VALUE t_get_peername (VALUE self, VALUE signature)
307
309
  {
308
310
  struct sockaddr s;
309
- if (evma_get_peername (StringValuePtr (signature), &s)) {
311
+ if (evma_get_peername (NUM2ULONG (signature), &s)) {
310
312
  return rb_str_new ((const char*)&s, sizeof(s));
311
313
  }
312
314
 
@@ -320,7 +322,7 @@ t_get_sockname
320
322
  static VALUE t_get_sockname (VALUE self, VALUE signature)
321
323
  {
322
324
  struct sockaddr s;
323
- if (evma_get_sockname (StringValuePtr (signature), &s)) {
325
+ if (evma_get_sockname (NUM2ULONG (signature), &s)) {
324
326
  return rb_str_new ((const char*)&s, sizeof(s));
325
327
  }
326
328
 
@@ -334,7 +336,7 @@ t_get_subprocess_pid
334
336
  static VALUE t_get_subprocess_pid (VALUE self, VALUE signature)
335
337
  {
336
338
  pid_t pid;
337
- if (evma_get_subprocess_pid (StringValuePtr (signature), &pid)) {
339
+ if (evma_get_subprocess_pid (NUM2ULONG (signature), &pid)) {
338
340
  return INT2NUM (pid);
339
341
  }
340
342
 
@@ -352,8 +354,8 @@ static VALUE t_get_subprocess_status (VALUE self, VALUE signature)
352
354
  int status;
353
355
  pid_t pid;
354
356
 
355
- if (evma_get_subprocess_status (StringValuePtr (signature), &status)) {
356
- if (evma_get_subprocess_pid (StringValuePtr (signature), &pid)) {
357
+ if (evma_get_subprocess_status (NUM2ULONG (signature), &status)) {
358
+ if (evma_get_subprocess_pid (NUM2ULONG (signature), &pid)) {
357
359
  proc_status = rb_obj_alloc(rb_cProcStatus);
358
360
  rb_iv_set(proc_status, "status", INT2FIX(status));
359
361
  rb_iv_set(proc_status, "pid", INT2FIX(pid));
@@ -378,7 +380,7 @@ t_get_comm_inactivity_timeout
378
380
 
379
381
  static VALUE t_get_comm_inactivity_timeout (VALUE self, VALUE signature)
380
382
  {
381
- return rb_float_new(evma_get_comm_inactivity_timeout(StringValuePtr(signature)));
383
+ return rb_float_new(evma_get_comm_inactivity_timeout(NUM2ULONG (signature)));
382
384
  }
383
385
 
384
386
  /*****************************
@@ -388,11 +390,31 @@ t_set_comm_inactivity_timeout
388
390
  static VALUE t_set_comm_inactivity_timeout (VALUE self, VALUE signature, VALUE timeout)
389
391
  {
390
392
  float ti = RFLOAT_VALUE(timeout);
391
- if (evma_set_comm_inactivity_timeout (StringValuePtr (signature), ti));
393
+ if (evma_set_comm_inactivity_timeout (NUM2ULONG (signature), ti));
392
394
  return Qtrue;
393
395
  return Qfalse;
394
396
  }
395
397
 
398
+ /*****************************
399
+ t_get_pending_connect_timeout
400
+ *****************************/
401
+
402
+ static VALUE t_get_pending_connect_timeout (VALUE self, VALUE signature)
403
+ {
404
+ return rb_float_new(evma_get_pending_connect_timeout(NUM2ULONG (signature)));
405
+ }
406
+
407
+ /*****************************
408
+ t_set_pending_connect_timeout
409
+ *****************************/
410
+
411
+ static VALUE t_set_pending_connect_timeout (VALUE self, VALUE signature, VALUE timeout)
412
+ {
413
+ float ti = RFLOAT_VALUE(timeout);
414
+ if (evma_set_pending_connect_timeout (NUM2ULONG (signature), ti));
415
+ return Qtrue;
416
+ return Qfalse;
417
+ }
396
418
 
397
419
  /***************
398
420
  t_send_datagram
@@ -400,7 +422,7 @@ t_send_datagram
400
422
 
401
423
  static VALUE t_send_datagram (VALUE self, VALUE signature, VALUE data, VALUE data_length, VALUE address, VALUE port)
402
424
  {
403
- int b = evma_send_datagram (StringValuePtr (signature), StringValuePtr (data), FIX2INT (data_length), StringValuePtr(address), FIX2INT(port));
425
+ int b = evma_send_datagram (NUM2ULONG (signature), StringValuePtr (data), FIX2INT (data_length), StringValuePtr(address), FIX2INT(port));
404
426
  return INT2NUM (b);
405
427
  }
406
428
 
@@ -411,7 +433,7 @@ t_close_connection
411
433
 
412
434
  static VALUE t_close_connection (VALUE self, VALUE signature, VALUE after_writing)
413
435
  {
414
- evma_close_connection (StringValuePtr (signature), ((after_writing == Qtrue) ? 1 : 0));
436
+ evma_close_connection (NUM2ULONG (signature), ((after_writing == Qtrue) ? 1 : 0));
415
437
  return Qnil;
416
438
  }
417
439
 
@@ -421,7 +443,7 @@ t_report_connection_error_status
421
443
 
422
444
  static VALUE t_report_connection_error_status (VALUE self, VALUE signature)
423
445
  {
424
- int b = evma_report_connection_error_status (StringValuePtr (signature));
446
+ int b = evma_report_connection_error_status (NUM2ULONG (signature));
425
447
  return INT2NUM (b);
426
448
  }
427
449
 
@@ -437,10 +459,14 @@ static VALUE t_connect_server (VALUE self, VALUE server, VALUE port)
437
459
  // Specifically, if the value of port comes in as a string rather than an integer,
438
460
  // NUM2INT will throw a type error, but FIX2INT will generate garbage.
439
461
 
440
- const char *f = evma_connect_to_server (NULL, 0, StringValuePtr(server), NUM2INT(port));
441
- if (!f || !*f)
442
- rb_raise (rb_eRuntimeError, "no connection");
443
- return rb_str_new2 (f);
462
+ try {
463
+ const unsigned long f = evma_connect_to_server (NULL, 0, StringValuePtr(server), NUM2INT(port));
464
+ if (!f)
465
+ rb_raise (EM_eConnectionError, "no connection");
466
+ return ULONG2NUM (f);
467
+ } catch (std::runtime_error e) {
468
+ rb_raise (EM_eConnectionError, e.what());
469
+ }
444
470
  }
445
471
 
446
472
  /*********************
@@ -453,15 +479,14 @@ static VALUE t_bind_connect_server (VALUE self, VALUE bind_addr, VALUE bind_port
453
479
  // Specifically, if the value of port comes in as a string rather than an integer,
454
480
  // NUM2INT will throw a type error, but FIX2INT will generate garbage.
455
481
 
456
- const char *f;
457
482
  try {
458
- f = evma_connect_to_server (StringValuePtr(bind_addr), NUM2INT(bind_port), StringValuePtr(server), NUM2INT(port));
459
- if (!f || !*f)
460
- rb_raise (rb_eRuntimeError, "no connection");
483
+ const unsigned long f = evma_connect_to_server (StringValuePtr(bind_addr), NUM2INT(bind_port), StringValuePtr(server), NUM2INT(port));
484
+ if (!f)
485
+ rb_raise (EM_eConnectionError, "no connection");
486
+ return ULONG2NUM (f);
461
487
  } catch (std::runtime_error e) {
462
- rb_sys_fail(e.what());
488
+ rb_raise (EM_eConnectionError, e.what());
463
489
  }
464
- return rb_str_new2 (f);
465
490
  }
466
491
 
467
492
  /*********************
@@ -470,31 +495,113 @@ t_connect_unix_server
470
495
 
471
496
  static VALUE t_connect_unix_server (VALUE self, VALUE serversocket)
472
497
  {
473
- const char *f = evma_connect_to_unix_server (StringValuePtr(serversocket));
474
- if (!f || !*f)
498
+ const unsigned long f = evma_connect_to_unix_server (StringValuePtr(serversocket));
499
+ if (!f)
475
500
  rb_raise (rb_eRuntimeError, "no connection");
476
- return rb_str_new2 (f);
501
+ return ULONG2NUM (f);
477
502
  }
478
503
 
479
504
  /***********
480
505
  t_attach_fd
481
506
  ***********/
482
507
 
483
- static VALUE t_attach_fd (VALUE self, VALUE file_descriptor, VALUE read_mode, VALUE write_mode)
508
+ static VALUE t_attach_fd (VALUE self, VALUE file_descriptor, VALUE watch_mode)
484
509
  {
485
- const char *f = evma_attach_fd (NUM2INT(file_descriptor), (read_mode == Qtrue) ? 1 : 0, (write_mode == Qtrue) ? 1 : 0);
486
- if (!f || !*f)
510
+ const unsigned long f = evma_attach_fd (NUM2INT(file_descriptor), watch_mode == Qtrue);
511
+ if (!f)
487
512
  rb_raise (rb_eRuntimeError, "no connection");
488
- return rb_str_new2 (f);
513
+ return ULONG2NUM (f);
489
514
  }
490
515
 
491
516
  /***********
492
517
  t_detach_fd
493
518
  ***********/
494
519
 
495
- static VALUE t_detach_fd (VALUE self, VALUE signature)
520
+ static VALUE t_detach_fd (VALUE self, VALUE signature)
521
+ {
522
+ return INT2NUM(evma_detach_fd (NUM2ULONG (signature)));
523
+ }
524
+
525
+ /**************
526
+ t_get_sock_opt
527
+ **************/
528
+
529
+ static VALUE t_get_sock_opt (VALUE self, VALUE signature, VALUE lev, VALUE optname)
530
+ {
531
+ int fd = evma_get_file_descriptor (NUM2ULONG (signature));
532
+ int level = NUM2INT(lev), option = NUM2INT(optname);
533
+ socklen_t len = 128;
534
+ char buf[128];
535
+
536
+ if (getsockopt(fd, level, option, buf, &len) < 0)
537
+ rb_sys_fail("getsockopt");
538
+
539
+ return rb_str_new(buf, len);
540
+ }
541
+
542
+ /********************
543
+ t_is_notify_readable
544
+ ********************/
545
+
546
+ static VALUE t_is_notify_readable (VALUE self, VALUE signature)
547
+ {
548
+ return evma_is_notify_readable(NUM2ULONG (signature)) ? Qtrue : Qfalse;
549
+ }
550
+
551
+ /*********************
552
+ t_set_notify_readable
553
+ *********************/
554
+
555
+ static VALUE t_set_notify_readable (VALUE self, VALUE signature, VALUE mode)
496
556
  {
497
- return INT2NUM(evma_detach_fd (StringValuePtr(signature)));
557
+ evma_set_notify_readable(NUM2ULONG (signature), mode == Qtrue);
558
+ return Qnil;
559
+ }
560
+
561
+ /********************
562
+ t_is_notify_readable
563
+ ********************/
564
+
565
+ static VALUE t_is_notify_writable (VALUE self, VALUE signature)
566
+ {
567
+ return evma_is_notify_writable(NUM2ULONG (signature)) ? Qtrue : Qfalse;
568
+ }
569
+
570
+ /*********************
571
+ t_set_notify_writable
572
+ *********************/
573
+
574
+ static VALUE t_set_notify_writable (VALUE self, VALUE signature, VALUE mode)
575
+ {
576
+ evma_set_notify_writable(NUM2ULONG (signature), mode == Qtrue);
577
+ return Qnil;
578
+ }
579
+
580
+ /*******
581
+ t_pause
582
+ *******/
583
+
584
+ static VALUE t_pause (VALUE self, VALUE signature)
585
+ {
586
+ return evma_pause(NUM2ULONG (signature)) ? Qtrue : Qfalse;
587
+ }
588
+
589
+ /********
590
+ t_resume
591
+ ********/
592
+
593
+ static VALUE t_resume (VALUE self, VALUE signature)
594
+ {
595
+ return evma_resume(NUM2ULONG (signature)) ? Qtrue : Qfalse;
596
+ }
597
+
598
+ /**********
599
+ t_paused_p
600
+ **********/
601
+
602
+ static VALUE t_paused_p (VALUE self, VALUE signature)
603
+ {
604
+ return evma_is_paused(NUM2ULONG (signature)) ? Qtrue : Qfalse;
498
605
  }
499
606
 
500
607
  /*****************
@@ -503,10 +610,10 @@ t_open_udp_socket
503
610
 
504
611
  static VALUE t_open_udp_socket (VALUE self, VALUE server, VALUE port)
505
612
  {
506
- const char *f = evma_open_datagram_socket (StringValuePtr(server), FIX2INT(port));
507
- if (!f || !*f)
613
+ const unsigned long f = evma_open_datagram_socket (StringValuePtr(server), FIX2INT(port));
614
+ if (!f)
508
615
  rb_raise (rb_eRuntimeError, "no datagram socket");
509
- return rb_str_new2 (f);
616
+ return ULONG2NUM (f);
510
617
  }
511
618
 
512
619
 
@@ -600,10 +707,10 @@ t__write_file
600
707
 
601
708
  static VALUE t__write_file (VALUE self, VALUE filename)
602
709
  {
603
- const char *f = evma__write_file (StringValuePtr (filename));
604
- if (!f || !*f)
710
+ const unsigned long f = evma__write_file (StringValuePtr (filename));
711
+ if (!f)
605
712
  rb_raise (rb_eRuntimeError, "file not opened");
606
- return rb_str_new2 (f);
713
+ return ULONG2NUM (f);
607
714
  }
608
715
 
609
716
  /**************
@@ -628,15 +735,15 @@ static VALUE t_invoke_popen (VALUE self, VALUE cmd)
628
735
  }
629
736
  strings[len] = NULL;
630
737
 
631
- const char *f = evma_popen (strings);
632
- if (!f || !*f) {
738
+ const unsigned long f = evma_popen (strings);
739
+ if (!f) {
633
740
  char *err = strerror (errno);
634
741
  char buf[100];
635
742
  memset (buf, 0, sizeof(buf));
636
743
  snprintf (buf, sizeof(buf)-1, "no popen: %s", (err?err:"???"));
637
- rb_raise (rb_eRuntimeError, buf);
744
+ rb_raise (rb_eRuntimeError, "%s", buf);
638
745
  }
639
- return rb_str_new2 (f);
746
+ return ULONG2NUM (f);
640
747
  }
641
748
 
642
749
 
@@ -646,10 +753,10 @@ t_read_keyboard
646
753
 
647
754
  static VALUE t_read_keyboard (VALUE self)
648
755
  {
649
- const char *f = evma_open_keyboard();
650
- if (!f || !*f)
756
+ const unsigned long f = evma_open_keyboard();
757
+ if (!f)
651
758
  rb_raise (rb_eRuntimeError, "no keyboard reader");
652
- return rb_str_new2 (f);
759
+ return ULONG2NUM (f);
653
760
  }
654
761
 
655
762
 
@@ -660,7 +767,7 @@ t_watch_filename
660
767
  static VALUE t_watch_filename (VALUE self, VALUE fname)
661
768
  {
662
769
  try {
663
- return rb_str_new2(evma_watch_filename(StringValuePtr(fname)));
770
+ return ULONG2NUM(evma_watch_filename(StringValuePtr(fname)));
664
771
  } catch (std::runtime_error e) {
665
772
  rb_sys_fail(e.what());
666
773
  }
@@ -673,7 +780,7 @@ t_unwatch_filename
673
780
 
674
781
  static VALUE t_unwatch_filename (VALUE self, VALUE sig)
675
782
  {
676
- evma_unwatch_filename(StringValuePtr(sig));
783
+ evma_unwatch_filename(NUM2ULONG (sig));
677
784
  return Qnil;
678
785
  }
679
786
 
@@ -685,7 +792,7 @@ t_watch_pid
685
792
  static VALUE t_watch_pid (VALUE self, VALUE pid)
686
793
  {
687
794
  try {
688
- return rb_str_new2(evma_watch_pid(NUM2INT(pid)));
795
+ return ULONG2NUM(evma_watch_pid(NUM2INT(pid)));
689
796
  } catch (std::runtime_error e) {
690
797
  rb_sys_fail(e.what());
691
798
  }
@@ -698,7 +805,7 @@ t_unwatch_pid
698
805
 
699
806
  static VALUE t_unwatch_pid (VALUE self, VALUE sig)
700
807
  {
701
- evma_unwatch_pid(StringValuePtr(sig));
808
+ evma_unwatch_pid(NUM2ULONG (sig));
702
809
  return Qnil;
703
810
  }
704
811
 
@@ -722,9 +829,6 @@ t__epoll
722
829
 
723
830
  static VALUE t__epoll (VALUE self)
724
831
  {
725
- if (t__epoll_p(self) == Qfalse)
726
- return Qfalse;
727
-
728
832
  evma_set_epoll (1);
729
833
  return Qtrue;
730
834
  }
@@ -736,7 +840,7 @@ t__epoll_set
736
840
  static VALUE t__epoll_set (VALUE self, VALUE val)
737
841
  {
738
842
  if (t__epoll_p(self) == Qfalse)
739
- return Qfalse;
843
+ rb_raise (EM_eUnsupported, "epoll is not supported on this platform");
740
844
 
741
845
  evma_set_epoll (val == Qtrue ? 1 : 0);
742
846
  return val;
@@ -762,9 +866,6 @@ t__kqueue
762
866
 
763
867
  static VALUE t__kqueue (VALUE self)
764
868
  {
765
- if (t__kqueue_p(self) == Qfalse)
766
- return Qfalse;
767
-
768
869
  evma_set_kqueue (1);
769
870
  return Qtrue;
770
871
  }
@@ -776,7 +877,7 @@ t__kqueue_set
776
877
  static VALUE t__kqueue_set (VALUE self, VALUE val)
777
878
  {
778
879
  if (t__kqueue_p(self) == Qfalse)
779
- return Qfalse;
880
+ rb_raise (EM_eUnsupported, "kqueue is not supported on this platform");
780
881
 
781
882
  evma_set_kqueue (val == Qtrue ? 1 : 0);
782
883
  return val;
@@ -812,7 +913,7 @@ static VALUE t_send_file_data (VALUE self, VALUE signature, VALUE filename)
812
913
  * do this. For one thing it's ugly. For another, we can't be sure zero is never a real errno.
813
914
  */
814
915
 
815
- int b = evma_send_file_data_to_connection (StringValuePtr(signature), StringValuePtr(filename));
916
+ int b = evma_send_file_data_to_connection (NUM2ULONG (signature), StringValuePtr(filename));
816
917
  if (b == -1)
817
918
  rb_raise(rb_eRuntimeError, "File too large. send_file_data() supports files under 32k.");
818
919
  if (b > 0) {
@@ -821,7 +922,7 @@ static VALUE t_send_file_data (VALUE self, VALUE signature, VALUE filename)
821
922
  memset (buf, 0, sizeof(buf));
822
923
  snprintf (buf, sizeof(buf)-1, ": %s %s", StringValuePtr(filename),(err?err:"???"));
823
924
 
824
- rb_raise (rb_eIOError, buf);
925
+ rb_raise (rb_eIOError, "%s", buf);
825
926
  }
826
927
 
827
928
  return INT2NUM (0);
@@ -845,7 +946,7 @@ conn_get_outbound_data_size
845
946
  static VALUE conn_get_outbound_data_size (VALUE self)
846
947
  {
847
948
  VALUE sig = rb_ivar_get (self, Intern_at_signature);
848
- return INT2NUM (evma_get_outbound_data_size (StringValuePtr(sig)));
949
+ return INT2NUM (evma_get_outbound_data_size (NUM2ULONG (sig)));
849
950
  }
850
951
 
851
952
 
@@ -866,12 +967,17 @@ t_get_loop_time
866
967
 
867
968
  static VALUE t_get_loop_time (VALUE self)
868
969
  {
869
- VALUE cTime = rb_path2class("Time");
970
+ #ifndef HAVE_RB_TIME_NEW
971
+ static VALUE cTime = rb_path2class("Time");
972
+ static ID at = rb_intern("at");
973
+ #endif
974
+
870
975
  if (gCurrentLoopTime != 0) {
871
- return rb_funcall(cTime,
872
- rb_intern("at"),
873
- 1,
874
- INT2NUM(gCurrentLoopTime));
976
+ #ifndef HAVE_RB_TIME_NEW
977
+ return rb_funcall(cTime, at, 2, INT2NUM(gCurrentLoopTime / 1000000), INT2NUM(gCurrentLoopTime % 1000000));
978
+ #else
979
+ return rb_time_new(gCurrentLoopTime / 1000000, gCurrentLoopTime % 1000000);
980
+ #endif
875
981
  }
876
982
  return Qnil;
877
983
  }
@@ -881,9 +987,9 @@ static VALUE t_get_loop_time (VALUE self)
881
987
  t_start_proxy
882
988
  **************/
883
989
 
884
- static VALUE t_start_proxy (VALUE self, VALUE from, VALUE to)
990
+ static VALUE t_start_proxy (VALUE self, VALUE from, VALUE to, VALUE bufsize)
885
991
  {
886
- evma_start_proxy(StringValuePtr(from), StringValuePtr(to));
992
+ evma_start_proxy(NUM2ULONG (from), NUM2ULONG (to), NUM2ULONG(bufsize));
887
993
  return Qnil;
888
994
  }
889
995
 
@@ -894,7 +1000,7 @@ t_stop_proxy
894
1000
 
895
1001
  static VALUE t_stop_proxy (VALUE self, VALUE from)
896
1002
  {
897
- evma_stop_proxy(StringValuePtr(from));
1003
+ evma_stop_proxy(NUM2ULONG (from));
898
1004
  return Qnil;
899
1005
  }
900
1006
 
@@ -955,9 +1061,11 @@ extern "C" void Init_rubyeventmachine()
955
1061
  EmModule = rb_define_module ("EventMachine");
956
1062
  EmConnection = rb_define_class_under (EmModule, "Connection", rb_cObject);
957
1063
 
958
- rb_define_class_under (EmModule, "NoHandlerForAcceptedConnection", rb_eException);
1064
+ rb_define_class_under (EmModule, "NoHandlerForAcceptedConnection", rb_eRuntimeError);
1065
+ EM_eConnectionError = rb_define_class_under (EmModule, "ConnectionError", rb_eRuntimeError);
959
1066
  EM_eConnectionNotBound = rb_define_class_under (EmModule, "ConnectionNotBound", rb_eRuntimeError);
960
1067
  EM_eUnknownTimerFired = rb_define_class_under (EmModule, "UnknownTimerFired", rb_eRuntimeError);
1068
+ EM_eUnsupported = rb_define_class_under (EmModule, "Unsupported", rb_eRuntimeError);
961
1069
 
962
1070
  rb_define_module_function (EmModule, "initialize_event_machine", (VALUE(*)(...))t_initialize_event_machine, 0);
963
1071
  rb_define_module_function (EmModule, "run_machine", (VALUE(*)(...))t_run_machine_without_threads, 0);
@@ -977,10 +1085,19 @@ extern "C" void Init_rubyeventmachine()
977
1085
  rb_define_module_function (EmModule, "bind_connect_server", (VALUE(*)(...))t_bind_connect_server, 4);
978
1086
  rb_define_module_function (EmModule, "connect_unix_server", (VALUE(*)(...))t_connect_unix_server, 1);
979
1087
 
980
- rb_define_module_function (EmModule, "attach_fd", (VALUE (*)(...))t_attach_fd, 3);
1088
+ rb_define_module_function (EmModule, "attach_fd", (VALUE (*)(...))t_attach_fd, 2);
981
1089
  rb_define_module_function (EmModule, "detach_fd", (VALUE (*)(...))t_detach_fd, 1);
1090
+ rb_define_module_function (EmModule, "get_sock_opt", (VALUE (*)(...))t_get_sock_opt, 3);
1091
+ rb_define_module_function (EmModule, "set_notify_readable", (VALUE (*)(...))t_set_notify_readable, 2);
1092
+ rb_define_module_function (EmModule, "set_notify_writable", (VALUE (*)(...))t_set_notify_writable, 2);
1093
+ rb_define_module_function (EmModule, "is_notify_readable", (VALUE (*)(...))t_is_notify_readable, 1);
1094
+ rb_define_module_function (EmModule, "is_notify_writable", (VALUE (*)(...))t_is_notify_writable, 1);
1095
+
1096
+ rb_define_module_function (EmModule, "pause_connection", (VALUE (*)(...))t_pause, 1);
1097
+ rb_define_module_function (EmModule, "resume_connection", (VALUE (*)(...))t_resume, 1);
1098
+ rb_define_module_function (EmModule, "connection_paused?", (VALUE (*)(...))t_paused_p, 1);
982
1099
 
983
- rb_define_module_function (EmModule, "start_proxy", (VALUE (*)(...))t_start_proxy, 2);
1100
+ rb_define_module_function (EmModule, "start_proxy", (VALUE (*)(...))t_start_proxy, 3);
984
1101
  rb_define_module_function (EmModule, "stop_proxy", (VALUE (*)(...))t_stop_proxy, 1);
985
1102
 
986
1103
  rb_define_module_function (EmModule, "watch_filename", (VALUE (*)(...))t_watch_filename, 1);
@@ -1015,6 +1132,8 @@ extern "C" void Init_rubyeventmachine()
1015
1132
  rb_define_module_function (EmModule, "get_subprocess_status", (VALUE(*)(...))t_get_subprocess_status, 1);
1016
1133
  rb_define_module_function (EmModule, "get_comm_inactivity_timeout", (VALUE(*)(...))t_get_comm_inactivity_timeout, 1);
1017
1134
  rb_define_module_function (EmModule, "set_comm_inactivity_timeout", (VALUE(*)(...))t_set_comm_inactivity_timeout, 2);
1135
+ rb_define_module_function (EmModule, "get_pending_connect_timeout", (VALUE(*)(...))t_get_pending_connect_timeout, 1);
1136
+ rb_define_module_function (EmModule, "set_pending_connect_timeout", (VALUE(*)(...))t_set_pending_connect_timeout, 2);
1018
1137
  rb_define_module_function (EmModule, "set_rlimit_nofile", (VALUE(*)(...))t_set_rlimit_nofile, 1);
1019
1138
  rb_define_module_function (EmModule, "get_connection_count", (VALUE(*)(...))t_get_connection_count, 0);
1020
1139