Home Manual Reference Source

src/recognizer/websocket/v4/Cdkv4WSBuilder.js

import { recognizerLogger as logger } from '../../../configuration/LoggerConfig';
import * as CryptoHelper from '../../CryptoHelper';
import * as NetworkWSInterface from '../networkWSInterface';
import * as RecognizerContext from '../../../model/RecognizerContext';
import Constants from '../../../configuration/Constants';
import {
  buildNewContentPackageInput,
  buildRestoreIInkSessionInput,
  buildNewContentPart,
  buildOpenContentPart,
  buildConfiguration,
  buildSetTheme,
  buildSetPenStyle
} from './Cdkv4WSIInkRecognizer';

/**
 * A CDK v4 websocket dialog have this sequence :
 * ---------- Client ------------------------------------- Server ----------------------------------
 * init (send the new content package) ================>
 *                                       <=========== hmacChallenge
 * answerToHmacChallenge (send the hmac) =========>
 * newPart (send the parameters ) ===============>
 *                                       <=========== update
 * addStrokes (send the strokes ) ============>
 *                                       <=========== update
 */

function buildHmacMessage(configuration, message) {
  return {
    type: 'hmac',
    hmac: CryptoHelper.computeHmac(message.data.hmacChallenge, configuration.recognitionParams.server.applicationKey, configuration.recognitionParams.server.hmacKey)
  };
}

/**
 * This function bind the right behaviour when a message is receive by the websocket.
 * @param {DestructuredPromise} destructuredPromise
 * @param {RecognizerContext} recognizerContext Current recognizer context
 * @return {function} Callback to handle WebSocket results
 */
export function buildWebSocketCallback(destructuredPromise, recognizerContext) {
  return (message) => {
    const recognizerContextRef = recognizerContext;
    // Handle websocket messages
    logger.trace(`${message.type} websocket callback`, message);
    const recognitionContext = recognizerContext.recognitionContexts[recognizerContext.recognitionContexts.length - 1];
    logger.debug('Current recognition context', recognitionContext);

    switch (message.type) {
      case 'open':
        if (recognizerContext.sessionId) {
          NetworkWSInterface.send(recognizerContext, buildRestoreIInkSessionInput(recognizerContext.editor.configuration, recognizerContext.editor.domElement, recognizerContext.sessionId));
        } else {
          NetworkWSInterface.send(recognizerContext, buildNewContentPackageInput(recognizerContext.editor.configuration, recognizerContext.editor.domElement));
        }
        break;
      case 'message':
        logger.debug(`Receiving ${message.data.type} message`, message);
        switch (message.data.type) {
          case 'ack':
            if (message.data.hmacChallenge) {
              NetworkWSInterface.send(recognizerContext, buildHmacMessage(recognizerContext.editor.configuration, message));
            }
            if (message.data.iinkSessionId) {
              recognizerContextRef.sessionId = message.data.iinkSessionId;
            }
            break;
          case 'newPart':
            break;
          case 'contentPackageDescription':
            recognizerContextRef.currentReconnectionCount = 0;
            recognizerContextRef.contentPartCount = message.data.contentPartCount;
            NetworkWSInterface.send(recognizerContext, buildConfiguration(recognizerContext.editor.configuration));
            if (recognizerContextRef.currentPartId) { // FIXME: Ugly hack to resolve init promise after opening part
              NetworkWSInterface.send(recognizerContext, buildOpenContentPart(recognizerContext.editor.configuration, recognizerContext.currentPartId));
            } else {
              NetworkWSInterface.send(recognizerContext, buildNewContentPart(recognizerContext.editor.configuration));
            }
            break;
          case 'partChanged':
            if (message.data.partId) {
              recognizerContextRef.currentPartId = message.data.partId;
            }
            recognizerContextRef.initialized = true;
            NetworkWSInterface.send(recognizerContext, buildSetTheme(recognizerContext.editor.theme));
            NetworkWSInterface.send(recognizerContext, buildSetPenStyle(recognizerContext.editor.penStyle));
            recognitionContext.callback(undefined, message.data);
            destructuredPromise.resolve(recognitionContext);
            break;
          case 'contentChanged':
            if (message.data.canUndo !== undefined) {
              recognizerContextRef.canUndo = message.data.canUndo;
            }
            if (message.data.canRedo !== undefined) {
              recognizerContextRef.canRedo = message.data.canRedo;
            }
            recognitionContext.callback(undefined, message.data);
            break;
          case 'exported':
            recognitionContext.callback(undefined, message.data);
            break;
          case 'svgPatch':
            recognitionContext.callback(undefined, message.data);
            break;
          case 'idle':
            recognizerContextRef.idle = true;
            recognitionContext.callback(undefined, message.data);
            break;
          case 'error':
            logger.debug('Error detected stopping all recognition', message);
            if (recognitionContext) {
              recognitionContext.callback(message.data);
            } else {
              destructuredPromise.reject(Object.assign({}, message.data, { recoverable: false }));
            }
            break;
          default :
            logger.warn('This is something unexpected in current recognizer. Not the type of message we should have here.', message);
        }
        break;
      case 'error':
        logger.debug('Error detected stopping all recognition', message);
        if (recognitionContext) {
          recognitionContext.callback(Object.assign({}, message, { recoverable: false }));
        } else {
          destructuredPromise.reject(Object.assign({}, message, { recoverable: false }));
        }
        break;
      case 'close':
        logger.debug('Close detected stopping all recognition', message);
        recognizerContextRef.initialized = false;
        recognizerContextRef.canRedo = false;
        recognizerContextRef.canUndo = false;
        if (recognitionContext) {
          recognitionContext.callback(undefined, message);
        } else {
          destructuredPromise.reject(message);
        }
        break;
      default :
        logger.warn('This is something unexpected in current recognizer. Not the type of message we should have here.', message);
    }
  }
    ;
}