From: Brian Candler Date: 2009-01-24T04:59:33+09:00 Subject: Re: Choosing the most appropiate Ruby version and programming model to develop a SIP server I単aki Baz Castillo wrote: >> Ah, then in principle it should scale Rails-like: >> - each process accepts *one* inbound TCP connection (*) >> - it listens for SIP messages, and sends SIP responses, on that one >> socket >> - call state is held in regular objects (rather than threads) > > Could you please explain this last point? Well, your main loop could be something like this: while true next_timeout = timer_queue.first.timestamp t = next_timeout - Time.now if select([sock], nil, nil, t < 0 ? 0 : t) ... read and handle an incoming message end if t <= 0 ... handle a timeout end end Then, when you handle each incoming message, you will have to look at attributes of this message to see if it's a new call, or references an existing call. If it's an existing call, then you look it up in some data structure: calls = {} # callid => CallState You process the incoming message based on its contents combined with the stored state, update the state, send a reply if necessary, and loop round. It's still bog-standard event-based programming, but since you are not talking to any untrusted party (the upstream is your own trusted SIP proxy) you probably don't have to worry about protocol violations or long pauses mid-way through a message. (And even if you did, you could just have one Thread reading and decoding inbound messages on the socket, and pushing the completed messages into a Queue for another Thread to pick off and process) What you could gain from Fiber-based models (Revactor?) in 1.9 is the ability to write your code in a more linear style, rather than as a state machine. I don't know how well SIP would map onto that. >> - timeouts can be done by means of a timer queue > > Any example of it? Not to hand. A good queue needs to make it easy to: - pop items off the front - locate and drop items in the middle (cancelling timers) - insert new timers in the middle and locate the correct place to put them A doubly-linked list is fine for small numbers of timers, but when you get into the hundreds you'll want something more like a priority queue. > Should then I really discard > EventMachine for this project? I only have minimal experience of it, with Swiftiply. Unfortunately that was a bad experience, but that may have been Swiftiply's fault rather than EM's. (I had an easily reproducible crash, but it was ignored in the Swiftiply mailing list and tracker) But I don't see that EM gives you much benefit, if you're only handling a single TCP connection per process. It might give you a decent timer queue implementation I suppose; I haven't looked at it. > PD: Would you *strongly* recommend me to avoid Ruby for this task? I can only speak for myself. I have a lot of experience with Ruby, and have only dabbled with Erlang, but this looks like such a hand-in-glove fit for Erlang that it would prompt me to go that way. If there's a half-decent SIP stack already written, I think that would compensate at least partly for the additional learning curve. But there could be other overriding concerns to lean towards Ruby (e.g. time to market, team constraints) > PPD: If not, any Ruby "version" and programming model implementation > (mantained and robust) running on that Ruby version? (I know my question > is > very difficult to answer, but I would really appreciate it). I don't have enough experience with a wide enough range implementations to answer that properly. 1.8.6p114 has been good to me. You have to be very careful with later 1.8.6's to avoid the broken ones. I tried Jruby once, taking an existing Rails app and packaging it as a war file with warbler. With no clients using it, the JVM took about 600MB of RSS, and the response time was rubbish. However that was a year or so ago, and there are plenty of people who swear by (rather than at) the J-word. At least with MRI, I know that if it breaks, at worst I can debug it with gdb. The whole (1.8) codebase is only a few megs. I wouldn't know where to start fixing a problem with the JVM. Regards, Brian. -- Posted via http://www.ruby-forum.com/.