Fixed reconnect Bugs.

This commit is contained in:
Valentin Boettcher 2017-08-14 19:33:44 +02:00
parent 5c2b362dcd
commit 5f19649fc8
8 changed files with 56 additions and 36 deletions

View file

@ -26,6 +26,7 @@ let actions = {
SET_SNAPSHOT_FAILED: 'SET_SNAPSHOT_FAILED',
SET_SNAPSHOT_TAKEN: 'SET_SNAPSHOT_TAKEN',
SET_ERROR: 'SET_ERROR',
SET_ERROR_RESOLVED: 'SET_ERROR_RESOLVED',
TRY_RECONNECT: 'TRY_RECONNECT',
STOP_ERROR_HANDLING: 'STOP_ERROR_HANDLING',
@ -147,6 +148,12 @@ creators.setError = function(error, stdout, stderr) {
};
};
creators.setErrorResolved = function() {
return {
type: actions.SET_ERROR_RESOLVED
};
};
creators.setTryReconnect = function(to) {
return {
type: actions.TRY_RECONNECT,

View file

@ -110,9 +110,6 @@ class Commander {
config = _getConfig;
dispatch = _dispatch;
// Create the FFMPEG-Command initially.
this.createCommands();
// Register events.
cmd.on('error', crashed);
cmd.on('end', crashed); // Can posibly be an error.
@ -151,6 +148,9 @@ Commander.prototype.start = function() {
// Set the Status to starting.
dispatch(requestStart());
// Create the FFMPEG-Command initially.
this.createCommands();
new Promise((resolve, reject) => {
cmd.once('start', resolve);
cmd.prependOnceListener('error', reject);
@ -179,7 +179,7 @@ Commander.prototype.restart = function() {
dispatch(self.stop()).then(() => {
dispatch(self.start()).then(() => {
resolve("Successfully restarted.");
}).catch((message) => reject("Could not start!", message)); // TODO: CD
}).catch((message) => reject({ message: "Could not restart!", details: message })); // TODO: CD
});
});
});
@ -199,6 +199,7 @@ Commander.prototype.stop = function() {
return new Promise((resolve, reject) => {
// Set the Status to starting.
dispatch(errorHandling.stopHandling());
dispatch(requestStop());
new Promise((resolve, reject) => {
@ -330,7 +331,7 @@ function crashed(error, stdout, stderr) {
let errorCode, handler;
// We stopped...
if (getState().stream.running === 'STOPPED')
if (getState().stream.running === 'STOPPED' || getState().stream.running === 'STOPPING')
return;
// Can't connect to the Camera
@ -343,8 +344,9 @@ function crashed(error, stdout, stderr) {
// Can't connect to the Internet / YouTube
else if (error.message.indexOf(source + 'Input/output error') > -1 || error.message.indexOf('rtmp://a.rtmp.youtube.com/live2/' + config().key) > -1) {
errorCode = 1;
handler = errorHandling.handlers.tryReconnect('a.rtmp.youtube.com/live2/', 1935,
() => dispatch(self.start()));
() => dispatch(self.start()));
}
// Wrong FFMPEG Executable
@ -361,16 +363,19 @@ function crashed(error, stdout, stderr) {
errorCode = 3;
// Just restart in a Second.
setTimeout(function() {
setTimeout(() => {
dispatch(self.start());
}, 1000);
}
dispatch(setError(errorCode, stdout, stderr)); // NOTE: Maybe no STDOUT
// Handle the error if possible.
if (handler)
dispatch(handler);
setTimeout(() => {
dispatch(handler);
}, 1000);
}

View file

@ -30,6 +30,7 @@ const {
SET_STOPPED,
REQUEST_RESTART,
SET_ERROR,
SET_ERROR_RESOLVED,
TRY_RECONNECT,
HYDRATE,
SET_CONNECTED,
@ -141,6 +142,7 @@ Communicator.prototype.sendAction = function(action) {
switch (action.type) {
case SET_STARTED:
case SET_STOPPED:
case SET_ERROR_RESOLVED:
type = 'startStop';
change = {
running: state.stream.running == 'RUNNING' ? 0 : 1, // TODO: CD
@ -348,7 +350,7 @@ function handleCommand(command, callback) {
dispatch(commander.start()).then(msg => answerSuccess(msg)).catch(error => answerError(error));
break;
case commands.RESTART:
dispatch(commander.restart()).then(msg => answerSuccess(msg)).catch(error => answerError(error));
dispatch(commander.restart()).then(msg => answerSuccess(msg)).catch(error => answerError(error.message + ' ' + error.details));
break;
case commands.UPDATE_CONFIG:
dispatch(updateConfig(command.data)).then(msg => answerSuccess(msg)).catch(err => answerError(err));

View file

@ -3,7 +3,8 @@
* @description Provides error Handlers
*/
const http = require('http');
const net = require('net');
const {
TRY_RECONNECT,
@ -12,7 +13,8 @@ const {
const {
setTryReconnect,
stopErrorHandling
stopErrorHandling,
setErrorResolved
} = require('./actions.js').creators;
///////////////////////////////////////////////////////////////////////////////
@ -46,15 +48,15 @@ module.exports.stopHandling = function() {
return (dispatch, getState) => {
let stopper,
handler = handlers[getState().stream.handleError];
if (!getState().stream.handleError)
return Promise.resolve();
if (!handler)
return Promise.resolve();
dispatch(stopErrorHandling());
stopper = handler.stop();
dispatch(stopErrorHandling());
stopper = handler.stop();
if (!stopper.then)
return Promise.resolve();
@ -92,31 +94,32 @@ function tryReconnect() {
reconnect();
function reconnect() {
// Somebody has stopped it.
if(!getState().stream.handleError)
return;
// Somebody has stopped it.
if (!getState().stream.handleError)
return;
http.get({
host: host.split('/')[0],
port: port
}, function() {
const socket = new net.Socket();
const onError = () => {
connectHandle = setTimeout(function() {
reconnect();
}, 1000);
};
socket.setTimeout(1000);
socket.on('error', onError);
socket.on('timeout', onError);
socket.connect(port, host.split('/')[0], () => {
success();
}).on("error", function(error) {
if (error.message == "socket hang up") {
// Even if he doesn't like to talk to us, he's there.
success();
} else {
// try again
connectHandle = setTimeout(function() {
reconnect();
}, 1000);
}
socket.end();
});
}
function success() {
setTimeout(() => {
dispatch(stopErrorHandling());
dispatch(setErrorResolved());
after();
});
};

View file

@ -40,6 +40,7 @@ const {
SET_STOPPED,
REQUEST_RESTART,
SET_ERROR,
SET_ERROR_RESOLVED,
TRY_RECONNECT,
SET_CONNECTED,
SET_DISCONNECTED,
@ -61,13 +62,14 @@ const actionMessageMap = {
UPDATE_CONFIG: ['info', 'Config Updated'],
REQUEST_START: ['info', 'Starting Stream'],
SET_STARTED: ['success', 'Started Stream'],
REQUEST_STOP: ['info', 'Sopping Stream'],
REQUEST_STOP: ['info', 'Stopping Stream'],
SET_STOPPED: ['success', 'Stopped Stream'],
REQUEST_RESTART: ['info', 'Restarting Stream'],
TAKE_SNAPSHOT: ['info', 'Taking Snapshot.'],
SET_SNAPSHOT_FAILED: action => ['danger', `Snapshot failed: ${action.data}`],
SET_SNAPSHOT_TAKEN: ['success', 'Snapshot Taken'],
SET_ERROR: action => ['danger', `An error has occured: ${errors[action.data]}\n${action.stderr ? 'STDERR: ' + action.stderr + '\n' : ''}${action.stdout ? 'STDOUT: ' + action.stdout + '\n' : ''}`], // TODO: FILTER STDERR... STDOUT...
SET_ERROR_RESOLVED: ['success', 'The Problem was resolved.'],
TRY_RECONNECT: action => ['warning', `Trying to reconnect to: ${action.to[0]} on port ${action.to[1]}.`],
SET_CONNECTED: ['success', 'Connected to the Master-Server.'],
SET_DISCONNECTED: ['warning', 'Disconnected from the Master-Server.'],

View file

@ -15,6 +15,7 @@ const {
SET_SNAPSHOT_FAILED,
SET_SNAPSHOT_TAKEN,
SET_ERROR,
SET_ERROR_RESOLVED,
TRY_RECONNECT,
STOP_ERROR_HANDLING,
SET_CONNECTED,
@ -40,8 +41,8 @@ function error(state = false, action) {
case SET_ERROR:
return action.data;
case SET_STARTED:
return false;
case SET_STOPPED:
case SET_STOPPED:
case SET_ERROR_RESOLVED:
return false;
default:
return state;

View file

@ -350,7 +350,7 @@ SSHMan.middleware = store => next => action => {
action.data.sshLocalUser ||
action.data.camIP ||
action.data.camPanelPort) {
dispatch(self.restartTunnels());
dispatch(self.restartTunnels()).catch(() => {}); // TODO: Nicer error handling
}
}
return result;

2
todo
View file

@ -1,4 +1,4 @@
- restart enable.
- restart enable in webif
- update config commands (middleware)
- shared config
- update docs with GatewayPorts clientspecified