PageRenderTime 58ms CodeModel.GetById 16ms app.highlight 10ms RepoModel.GetById 26ms app.codeStats 0ms

/lib/socket.js

https://github.com/lucciano/zerorpc-node
JavaScript | 145 lines | 73 code | 23 blank | 49 comment | 8 complexity | 6672e94cb3679caa7ab3b9938861e1ca MD5 | raw file
  1// Open Source Initiative OSI - The MIT License (MIT):Licensing
  2//
  3// The MIT License (MIT)
  4// Copyright (c) 2012 DotCloud Inc (opensource@dotcloud.com)
  5//
  6// Permission is hereby granted, free of charge, to any person obtaining a
  7// copy of this software and associated documentation files (the "Software"),
  8// to deal in the Software without restriction, including without limitation
  9// the rights to use, copy, modify, merge, publish, distribute, sublicense,
 10// and/or sell copies of the Software, and to permit persons to whom the
 11// Software is furnished to do so, subject to the following conditions:
 12//
 13// The above copyright notice and this permission notice shall be included in
 14// all copies or substantial portions of the Software.
 15//
 16// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 17// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 18// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 19// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 20// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 21// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 22// DEALINGS IN THE SOFTWARE.
 23
 24var nodeUtil = require("util"),
 25    zmq = require("zmq"),
 26    nodeEvents = require("events"),
 27    events = require("./events"),
 28    util = require("./util"),
 29    channel = require("./channel");
 30
 31//The default channel capacity
 32var CHANNEL_CAPACITY = 100;
 33
 34//Creates a new socket
 35//zmqSocket : Object
 36//      The underlying ZeroMQ socket to use
 37function Socket(zmqSocket) {
 38    var self = this;
 39    self._zmqSocket = zmqSocket;
 40    util.eventProxy(self._zmqSocket, self, "error");
 41
 42    var error = function(message) {
 43        self.emit("error", message);
 44    };
 45
 46    self._zmqSocket.on("message", function() {
 47        //Deserialize the object and perform some sanity checks
 48        if(arguments[arguments.length - 2].length != 0) {
 49            return error("Expected second to last argument to be an empty buffer, but it is not");
 50        }
 51
 52        var envelope = Array.prototype.slice.call(arguments, 0, arguments.length - 2);
 53
 54        try {
 55            var event = events.deserialize(envelope, arguments[arguments.length - 1]);
 56        } catch(e) {
 57            return error("Invalid event: " + e);
 58        }
 59
 60        //Emit the event
 61        self.emit("socket/receive", event);
 62    });
 63}
 64
 65nodeUtil.inherits(Socket, nodeEvents.EventEmitter);
 66
 67//Sends a message on the socket
 68//event : Object
 69//      The ZeroRPC event to send
 70Socket.prototype.send = function(event) {
 71    var message = events.serialize(event);
 72    this._zmqSocket.send.call(this._zmqSocket, message);
 73};
 74
 75//Binds to a ZeroMQ endpoint
 76//endpoint : String
 77//      The ZeroMQ endpoint
 78Socket.prototype.bind = function(endpoint) {
 79    this._zmqSocket.bindSync(endpoint);
 80}
 81
 82//Connects to a ZeroMQ endpoint
 83//endpoint : String
 84//      The ZeroMQ endpoint
 85Socket.prototype.connect = function(endpoint) {
 86    this._zmqSocket.connect(endpoint);
 87}
 88
 89//Creates a new multiplexing socket
 90//zmqSocket : Object
 91//      The underlying ZeroMQ socket to use
 92function MultiplexingSocket(zmqSocket) {
 93    Socket.call(this, zmqSocket);
 94    var self = this;
 95
 96    //Map of open channel IDs => channel objects
 97    self.channels = {};
 98
 99    //Route events to a channel if possible; otherwise emit the event
100    self.on("socket/receive", function(event) {
101        var ch = self.channels[event.header.response_to || ""];
102
103        if(ch) {
104            ch.invoke(event);
105        } else {
106            self.emit("multiplexing-socket/receive", event);
107        }
108    });
109}
110
111nodeUtil.inherits(MultiplexingSocket, Socket);
112
113//Opens a new channel
114//srcEvent : Object or null
115//      The ZeroRPC event that caused the channel to be opened, or null if
116//      this is a locally opened channel.
117MultiplexingSocket.prototype.openChannel = function(srcEvent) {
118    if(srcEvent) {
119        var ch = new channel.ServerChannel(srcEvent, this, CHANNEL_CAPACITY);
120    } else {
121        var ch = new channel.ClientChannel(this, CHANNEL_CAPACITY);
122    }
123
124    this.channels[ch.id] = ch;
125    return ch;
126};
127
128//Closes the socket
129MultiplexingSocket.prototype.close = function() {
130    this._zmqSocket.close();
131    for(var id in this.channels) this.channels[id].close();
132};
133
134//Creates a new multiplexing socket server
135function server() {
136    return new MultiplexingSocket(zmq.socket("xrep"));
137}
138
139//Creates a new multiplexing socket client
140function client() {
141    return new MultiplexingSocket(zmq.socket("xreq"));
142}
143
144exports.server = server;
145exports.client = client;