I am using Socket.io to implement a signaling process, such as connect, call, answer, reject, etc... and also onUserCalling, onUserRejected, etc...

I don't know what is the best way to handle the all statuses, for example, if A is calling B, at that time A's status will be set as 'calling' and B's status will be 'onUserCalling'. So at the mean while C can call nor A neither B because their status are not 'available'.

But when things get complicated, it's very hard to control the status.

So does anyone know good material/blog post/pattern regarding this issue?

Thanks in advance.

有帮助吗?

解决方案

It sounds like you're looking for a state machine. There's a lot of reading you can do on state machines, but basically they represent a thing that can be in one of any number of states; the state of the machine can be changed by triggering appropriate events on the machine.

In your case, calling and onUserCalling are the states, and call, answer, reject, etc. are the events. By representing this as a state machine, you can keep track of which state a user is in and what states they can transition to based on the events.

As an example, here is some code on Plunker that demonstrates such a state machine. (Ignore the fact that the user interface interaction was built with AngularJS.) The state machine is defined via a library called JavaScript State Machine and is defined as such:

StateMachine.create({
  initial: 'ready',
  events: [
    { name: 'placeCall',    from: 'ready',               to: 'calling' },
    { name: 'receiveCall',  from: 'ready',               to: 'callWaiting' },
    { name: 'callAnswered', from: 'calling',             to: 'inCall' },
    { name: 'callRejected', from: 'calling',             to: 'ready' },
    { name: 'answerCall',   from: 'callWaiting',         to: 'inCall' },
    { name: 'rejectCall',   from: 'callWaiting',         to: 'ready' },
    { name: 'hangUp',       from: ['calling', 'inCall'], to: 'ready' }
  ]
});

This says that when the machine is in the ready state, we can trigger the placeCall event to change the state calling, or we can trigger the receiveCall event to change the state to callWaiting. Once the state has been changed to calling, we can move to either the inCall state or back to ready by triggering the callAnswered or callRejected events, respectively.

The state machine library can look into the events definition and tell you which events are allowed to be fired based on the current state of the machine. In the example, I've used this to only enable the buttons that will fire allowed events.

Most state machine libraries, including the JavaScript one I've used here, allow you to supply callbacks when you enter or leave certain events; this particular library also allows asynchronous event transitions, which may help when using the library with async Node.js code. You can find more information in the readme.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top