'use strict';

var Promise = require("bluebird");

function RTC (signallingService, channelFactory) {
    this.signallingService = signallingService;
    this.channelFactory = channelFactory;
    this.channelListeners = {};
}

RTC.prototype.join = function (localNode) {
    var self = this;
    this.signallingService.initialize(localNode);
    this.signallingService.on("offer", function(message) {
        self.handleOffer(message);
    });
}

RTC.prototype.getSignallingInfo = function () {
    return this.signallingService.getSignallingInfo();
}

RTC.prototype.onChannel = function (type, callback) {
    this.channelListeners[type] = callback;
}

RTC.prototype.openChannel = function (type, remotePointer) {
    var channel = this.channelFactory.createChannel(remotePointer);

    return channel.createOffer(type)
        .then(channel.waitForIceCandidates)
        .then(channel.sendOffer)
        .then(channel.waitForAnswer)
        .then(channel.handleAnswer)
        .then(channel.waitForChannelToOpen);
}

RTC.prototype.handleOffer = function (offerMessage) {
    var channelType = offerMessage.channelType;
    var listener = this.channelListeners[channelType];
    var remotePointer = offerMessage.sourcePointer;
    var correlationId = offerMessage.correlationId;

    if(listener) {
        var channel = this.channelFactory.createChannel(remotePointer, correlationId);

        return channel.createAnswer(offerMessage.sessionDescription, offerMessage.iceCandidates)
            .then(channel.waitForIceCandidates)
            .then(channel.sendAnswer)
            .then(channel.waitForChannelEstablishment)
            .then(channel.waitForChannelToOpen)
            .then(listener)
            .catch(Promise.TimeoutError, function(e) {
                console.error(e);
            })
            .finally(channel.close);
    }
    else {
        console.warn("No listener for channel type " + channelType + ", ignoring offer!");
    }
}

module.exports = RTC;

@@ -1007,16 +1007,241 @@
 lToOpen)
+%0A        .catch(function(error) %7B%0A            // If an error occurs here, cleanup our attempted channel%0A            // establishment resources before continuing%0A            channel.close();%0A            throw error;%0A        %7D)
 ;%0A%7D%0A%0ARTC

Fix resource leak when outgoing channel establishment fails