diff options
Diffstat (limited to 'js/demo')
81 files changed, 6004 insertions, 0 deletions
diff --git a/js/demo/ChatDemo/.gitignore b/js/demo/ChatDemo/.gitignore new file mode 100644 index 00000000000..c09a9ad9584 --- /dev/null +++ b/js/demo/ChatDemo/.gitignore @@ -0,0 +1,4 @@ +Chat.js +ChatSession.js +Client.min.js +Client.min.js.gz diff --git a/js/demo/ChatDemo/Chat.ice b/js/demo/ChatDemo/Chat.ice new file mode 100644 index 00000000000..944e903e791 --- /dev/null +++ b/js/demo/ChatDemo/Chat.ice @@ -0,0 +1,42 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Chat Demo is licensed to you under the terms described +// in the CHAT_DEMO_LICENSE file included in this distribution. +// +// ********************************************************************** + +#ifndef CHAT_ICE +#define CHAT_ICE + + +/** + * + * The Chat module defines types shared by definitions from + * ChatSession.ice and PollingChat.ice. + * + **/ +module Chat +{ + +/** + * + * The InvalidMessageException is raised when a user sends an invalid + * message to the server. A message is considered invalid if the + * message size exceeds the maximum message size. + * + **/ +exception InvalidMessageException +{ + /** + * + * The reason why the message was rejected by the server. + * + **/ + string reason; +}; + +}; + +#endif diff --git a/js/demo/ChatDemo/ChatSession.ice b/js/demo/ChatDemo/ChatSession.ice new file mode 100644 index 00000000000..e10958338ba --- /dev/null +++ b/js/demo/ChatDemo/ChatSession.ice @@ -0,0 +1,125 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Chat Demo is licensed to you under the terms described +// in the CHAT_DEMO_LICENSE file included in this distribution. +// +// ********************************************************************** + +#ifndef CHAT_SESSION_ICE +#define CHAT_SESSION_ICE + +#include <Ice/BuiltinSequences.ice> +#include <Glacier2/Session.ice> +#include <Chat.ice> + +module Chat +{ + +/** + * + * The ChatRoomCallback interface is the interface that clients implement + * as their callback object. + * + * The server calls operations of this interface to communicate + * with connected clients. + * + **/ +interface ChatRoomCallback +{ + /** + * + * The server invokes this operation when the client sets the callback + * for a session. This provides the client with the initial list of users + * currently in the chat room. + * + * @param users The names of users currently in the chat room. + * + **/ + void init(Ice::StringSeq users); + + /** + * + * The server invokes this operation to deliver a message + * that was sent to the chat room. + * + * @param name The name of the user that send the message. + * + * @param message The contents of the message. + * + * @param timestamp The time at which the message was sent. + * + **/ + void send(long timestamp, string name, string message); + + /** + * + * The server invokes this operation when a user joins + * the chat room. + * + * @param name The name of the user that joined the chat room. + * + * @param timestamp The time at which the user joined the chat room. + * + **/ + void join(long timestamp, string name); + + /** + * + * The servers invokes this operation when a user leaves + * the chat room. + * + * @param name The name of the user that left the chat room. + * + * @param timestamp The time at which the user left the chat room. + * + **/ + void leave(long timestamp, string name); +}; + +/** + * + * A ChatSession is a custom Glacier2::Session for clients that use + * Glacier2 and support callbacks (C++, Java, and .NET clients). + * + * @see Glacier2::Session + * + **/ +interface ChatSession extends Glacier2::Session +{ + /** + * + * The setCallback operation is called by clients to set the + * callback used to receive notification of activity in the + * room. Clients receive notifications as soon as they call this + * operation (before setCallback returns). + * + * The first callback made by the server is a call to + * ChatRoomCallback::init, which delivers the current list of + * users to the client. + * + * @param cb The callback the server uses to deliver notifications. + * + * @see ChatRoomCallback + * + **/ + void setCallback(ChatRoomCallback* cb); + + /** + * + * Send a message to the chat room. + * + * @param message The message to be sent. + * + * @return The time at which the message is sent. + * + * @throws InvalidMessageException should the message be invalid. + * + **/ + long send(string message) throws InvalidMessageException; +}; + +}; + +#endif diff --git a/js/demo/ChatDemo/Client.js b/js/demo/ChatDemo/Client.js new file mode 100644 index 00000000000..3912cfdcecf --- /dev/null +++ b/js/demo/ChatDemo/Client.js @@ -0,0 +1,601 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice is licensed to you under the terms described in the +// ICE_LICENSE file included in this distribution. +// +// ********************************************************************** + +(function(){ + +var Promise = Ice.Promise; +var RouterPrx = Glacier2.RouterPrx; +var ChatRoomCallbackPrx = Chat.ChatRoomCallbackPrx; +var ChatSessionPrx = Chat.ChatSessionPrx; + +// +// Chat client state +// +var State = {Disconnected: 0, Connecting: 1, Connected: 2}; +var maxMessageSize = 1024; +var communicator; +var username; +var state; +var hasError = false; + +var hostname = document.location.hostname || "127.0.0.1"; + +// +// Servant that implements the ChatCallback interface. +// The message operation just writes the received data +// to the output textarea. +// +var ChatCallbackI = Ice.Class(Chat.ChatRoomCallback, { + init: function(users) + { + users.forEach( + function(name) + { + userJoined(name); + }); + }, + send: function(timestamp, name, message) + { + if(name != username) + { + writeLine(formatDate(timestamp.toNumber()) + " - <" + name + "> - " + unescapeHtml(message)); + } + }, + join: function(timestamp, name) + { + writeLine(formatDate(timestamp.toNumber()) + " - <system-message> - " + name + " joined."); + userJoined(name); + }, + leave: function(timestamp, name) + { + writeLine(formatDate(timestamp.toNumber()) + " - <system-message> - " + name + " left."); + userLeft(name); + } +}); + +function userJoined(name) +{ + if(name == username) + { + $("#users").append("<li id=\"" + name + "\"><b>" + name + "</b></li>"); + } + else + { + $("#users").append("<li id=\"" + name + "\"><a href=\"#\">" + name + "</a></li>"); + $("#users #" + name).click( + function() + { + var s = $("#input").val(); + if(s.length > 0) + { + s += " "; + } + s += "@" + name + " "; + $("#input").val(s); + $("#input").focus(); + return false; + }); + } + $("#users").append("<li class=\"divider\"></li>"); +} + +function userLeft(name) +{ + $("#users #" + name).off("click"); + $("#users #" + name).next().remove(); + $("#users #" + name).remove(); +} + +var signin = function() +{ + assert(state === State.Disconnected); + setState(State.Connecting).then( + function() + { + // + // Initialize the communicator with the Ice.Default.Router property + // set to the chat demo Glacier2 router. + // + var id = new Ice.InitializationData(); + id.properties = Ice.createProperties(); + id.properties.setProperty("Ice.Default.Router", + "Glacier2/router:wss -p 9090 -h " + hostname + " -r /chatwss"); + communicator = Ice.initialize(id); + + // + // Get a proxy to the Glacier2 router using checkedCast to ensure + // the Glacier2 server is available. + // + return RouterPrx.checkedCast(communicator.getDefaultRouter()).then( + function(router) + { + // + // Create a session with the Glacier2 router. + // + return router.createSession( + $("#username").val(), $("#password").val()).then( + function(session) + { + run(router, ChatSessionPrx.uncheckedCast(session)); + }); + }); + } + ).exception( + function(ex) + { + // + // Handle any exceptions that occurred during session creation. + // + if(ex instanceof Glacier2.PermissionDeniedException) + { + setState(State.Disconnected, "permission denied:\n" + ex.reason); + } + else if(ex instanceof Glacier2.CannotCreateSessionException) + { + setState(State.Disconnected, "cannot create session:\n" + ex.reason); + } + else if(ex instanceof Ice.ConnectFailedException) + { + setState(State.Disconnected, "connection to server failed"); + } + else + { + setState(State.Disconnected, ex.toString()); + } + }); +}; + +var run = function(router, session) +{ + assert(state === State.Connecting); + // + // The chat promise is used to wait for the completion of chatting + // state. The completion could happen because the user signed out, + // or because there is an exception. + // + var chat = new Promise(); + // + // Get the session timeout and the router client category, then + // create the client object adapter. + // + // Use Ice.Promise.all to wait for the completion of all the + // calls. + // + Promise.all( + router.getSessionTimeout(), + router.getCategoryForClient(), + communicator.createObjectAdapterWithRouter("", router) + ).then( + function() + { + // + // The results of each promise are provided in an array. + // + var timeout = arguments[0][0]; + var category = arguments[1][0]; + var adapter = arguments[2][0]; + + // + // Call refreshSession in a loop to keep the + // session alive. + // + var refreshSession = function() + { + router.refreshSession().exception( + function(ex) + { + chat.fail(ex); + } + ).delay(timeout.toNumber() * 500).then( + function() + { + if(!chat.completed()) + { + refreshSession(); + } + }); + }; + refreshSession(); + + // + // Create the ChatCallback servant and add it to the + // ObjectAdapter. + // + var callback = ChatRoomCallbackPrx.uncheckedCast( + adapter.add(new ChatCallbackI(), + new Ice.Identity("callback", category))); + + // + // Set the chat session callback. + // + return session.setCallback(callback); + } + ).then( + function() + { + return setState(State.Connected); + } + ).then( + function() + { + // + // Process input events in the input textbox until + // the chat promise is completed. + // + $("#input").keypress( + function(e) + { + if(!chat.completed()) + { + // + // When enter key is pressed, we send a new message + // using the session's say operation and then reset + // the textbox contents. + // + if(e.which === 13) + { + var msg = $(this).val(); + if(msg.length > 0) + { + $(this).val(""); + if(msg.length > maxMessageSize) + { + writeLine("<system-message> - Message length exceeded, " + + "maximum length is " + maxMessageSize + " characters."); + } + else + { + session.send(msg).then( + function(timestamp) + { + writeLine(formatDate(timestamp.toNumber()) + " - <" + + username + "> - " + msg); + }, + function(ex) + { + if(ex instanceof Chat.InvalidMessageException) + { + writeLine("<system-message> - " + ex.reason); + } + else + { + chat.fail(ex); + } + }); + } + } + return false; + } + } + }); + + // + // Exit the chat loop accepting the chat promise. + // + $("#signout").click( + function(){ + chat.succeed(); + return false; + }); + + return chat; + } + ).finally( + function() + { + // + // Reset the input text box and chat output textarea. + // + $("#input").val(""); + $("#input").off("keypress"); + $("#signout").off("click"); + $("#output").val(""); + + // + // Destroy the session. + // + return router.destroySession(); + } + ).then( + function() + { + setState(State.Disconnected); + } + ).exception( + function(ex) + { + // + // Handle any exceptions that occurred while running. + // + setState(State.Disconnected, ex.toString()); + }); +}; + +// +// Do a transition from "from" screen to "to" screen. Return +// a promise that allows us to wait for the transition to +// complete. If to screen is undefined just animate out the +// from screen. +// +var transition = function(from, to) +{ + var p = new Ice.Promise(); + + $(from).animo({ animation: "flipOutX", keep: true }, + function() + { + $(from).css("display", "none"); + if(to) + { + $(to).css("display", "block") + .animo({ animation: "flipInX", keep: true }, + function(){ p.succeed(); }); + } + else + { + p.succeed(); + } + }); + return p; +}; + +// +// Set default height of output textarea +// +$("#output").height(300); + +// +// Animate the loading progress bar. +// +var w = 0; +var progress; + +var startProgress = function() +{ + if(!progress) + { + progress = setInterval( + function() + { + w = w >= 100 ? 0 : w + 1; + $("#loading .meter").css("width", w.toString() + "%"); + }, + 20); + } +}; + +var stopProgress = function(completed) +{ + if(progress) + { + clearInterval(progress); + progress = null; + if(completed) + { + $("#loading .meter").css("width", "100%"); + } + } +}; + +// +// Dismiss error message on click. +// +function dismissError() +{ + transition("#signin-alert"); + hasError = false; + return false; +} + +// +// Switch the state and return a promise that is fulfilled +// when state change completes. +// +function setState(newState, error) +{ + assert(state !== newState); + switch(newState) + { + case State.Disconnected: + { + assert(state === undefined || + state === State.Connecting || + state === State.Connected); + + $("#users a").off("click"); + $("#users").html(""); + $(window).off("beforeunload"); + + // + // First destroy the communicator if needed then do + // the screen transition. + // + return Promise.try( + function() + { + if(communicator) + { + var c = communicator; + communicator = null; + return c.destroy(); + } + } + ).finally( + function() + { + if(state !== undefined) + { + if(error) + { + hasError = true; + stopProgress(false); + $("#signin-alert span").text(error); + return transition("#loading", "#signin-alert").then( + function(){ + $("#loading .meter").css("width", "0%"); + $("#signin-form").css("display", "block") + .animo({ animation: "flipInX", keep: true }); + }); + } + else + { + return transition("#chat-form", "#signin-form"); + } + } + } + ).then( + function() + { + $("#username").focus(); + $("#username").keypress( + function(e) + { + // + // After enter key is pressed in the username input, + // switch focus to password input. + // + if(e.which === 13) + { + $("#password").focus(); + return false; + } + }); + + $("#password").keypress( + function(e) + { + // + // After enter key is pressed in the password input, + // sign-in. + // + if(e.which === 13) + { + signin(); + return false; + } + }); + + $("#signin").click(function(){ + signin(); + return false; + }); + + state = State.Disconnected; + }); + } + case State.Connecting: + { + assert(state === State.Disconnected); + username = formatUsername($("#username").val()); + + // + // Remove the signin form event handlers. + // + $("#username").off("keypress"); + $("#password").off("keypress"); + $("#signin").off("click"); + + // + // Dismiss any previous error message. + // + if(hasError) + { + dismissError(); + } + + // + // Setup a before unload handler to prevent accidentally navigating + // away from the page while the user is connected to the chat server. + // + $(window).on("beforeunload", + function() + { + return "If you navigate away from this page, the current chat session will be lost."; + }); + + // + // Transition to loading screen + // + return transition("#signin-form", "#loading").then( + function() + { + startProgress(); + state = State.Connecting; + }); + } + case State.Connected: + { + // + // Stop animating the loading progress bar and + // transition to the chat screen. + // + assert(state === State.Connecting); + stopProgress(true); + return transition("#loading", "#chat-form").then( + function() + { + $("#loading .meter").css("width", "0%"); + $("#input").focus(); + state = State.Connected; + }); + } + } +} +// +// Switch to initial state. +// +setState(State.Disconnected); + +function formatDate(timestamp) +{ + var d = new Date(); + d.setTime(timestamp); + return d.toLocaleTimeString().trim(); +} + +function formatUsername(s) +{ + return s.length < 2 ? + s.toUpperCase() : + s.substring(0, 1).toUpperCase() + s.substring(1, s.length).toLowerCase(); +} + +function writeLine(s) +{ + $("#output").val($("#output").val() + s + "\n"); + $("#output").scrollTop($("#output").get(0).scrollHeight); +} + +var entities = [ + {entity: /"/g, value: "\""}, + {entity: /'/g, value: "'"}, + {entity: /</g, value: "<"}, + {entity: />/g, value: ">"}, + {entity: /&/g, value: "&"}]; + +function unescapeHtml(msg) +{ + var e; + for(var i = 0; i < entities.length; ++i) + { + e = entities[i]; + msg = msg.replace(e.entity, e.value); + } + return msg; +} + +function assert(v) +{ + if(!v) + { + throw new Error("Assertion failed"); + } +} + +}()); diff --git a/js/demo/ChatDemo/Makefile b/js/demo/ChatDemo/Makefile new file mode 100644 index 00000000000..fd88dd8cf0e --- /dev/null +++ b/js/demo/ChatDemo/Makefile @@ -0,0 +1,32 @@ +# ********************************************************************** +# +# Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +# +# This copy of Ice is licensed to you under the terms described in the +# ICE_LICENSE file included in this distribution. +# +# ********************************************************************** + +top_srcdir = ../.. + +TARGETS = Chat.js ChatSession.js + +ifeq ($(OPTIMIZE),yes) +TARGETS := $(TARGETS) Client.min.js Client.min.js.gz +endif + +include $(top_srcdir)/config/Make.rules.js + +SLICE2JSFLAGS := $(SLICE2JSFLAGS) -I$(slicedir) -I. + + +ifeq ($(OPTIMIZE),yes) + +CLOSUREFLAGS := $(CLOSUREFLAGS) --warning_level QUIET + +Client.min.js Client.min.js.gz: $(libdir)/Ice.min.js $(libdir)/Glacier2.min.js Client.js Chat.js ChatSession.js + @rm -f browser/Client.min.js browser/Client.min.js.gz + java -jar $(CLOSURE_PATH)/compiler.jar $(CLOSUREFLAGS) --js $(libdir)/Ice.min.js $(libdir)/Glacier2.min.js \ + Chat.js ChatSession.js Client.js --js_output_file Client.min.js + gzip -c9 Client.min.js > Client.min.js.gz +endif diff --git a/js/demo/ChatDemo/Makefile.mak b/js/demo/ChatDemo/Makefile.mak new file mode 100644 index 00000000000..b5533e67469 --- /dev/null +++ b/js/demo/ChatDemo/Makefile.mak @@ -0,0 +1,42 @@ +# ********************************************************************** +# +# Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +# +# This copy of Ice is licensed to you under the terms described in the +# ICE_LICENSE file included in this distribution. +# +# ********************************************************************** + +top_srcdir = ..\.. + +TARGETS = Chat.js ChatSession.js + +!if "$(OPTIMIZE)" == "yes" +TARGETS = $(TARGETS) Client.min.js + +!if "$(GZIP_PATH)" != "" +TARGETS = $(TARGETS) Client.min.js.gz +!endif + +!endif + +!include $(top_srcdir)\config\Make.rules.mak.js + +SLICE2JSFLAGS = $(SLICE2JSFLAGS) -I"$(slicedir)" -I. + +!if "$(OPTIMIZE)" == "yes" + +CLOSUREFLAGS = $(CLOSUREFLAGS) --warning_level QUIET + +Client.min.js: Client.js Chat.js ChatSession.js $(libdir)\Ice.min.js $(libdir)\Glacier2.min.js + @del /q Client.min.js + java -jar $(CLOSURE_PATH)\compiler.jar $(CLOSUREFLAGS) --js $(libdir)\Ice.js $(libdir)\Glacier2.js \ + Chat.js ChatSession.js Client.js --js_output_file Client.min.js + +!if "$(GZIP_PATH)" != "" +Client.min.js.gz: Client.min.js + @del /q Client.min.js.gz + "$(GZIP_PATH)" -c9 Client.min.js > Client.min.js.gz +!endif + +!endif diff --git a/js/demo/ChatDemo/build.js b/js/demo/ChatDemo/build.js new file mode 100644 index 00000000000..b79242b8999 --- /dev/null +++ b/js/demo/ChatDemo/build.js @@ -0,0 +1,10 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice is licensed to you under the terms described in the +// ICE_LICENSE file included in this distribution. +// +// ********************************************************************** + +require ("../../config/build").build(__dirname, ["Chat.ice", "ChatSession.ice"], ["-I."]); diff --git a/js/demo/ChatDemo/index.html b/js/demo/ChatDemo/index.html new file mode 100644 index 00000000000..22a5e1ba836 --- /dev/null +++ b/js/demo/ChatDemo/index.html @@ -0,0 +1,271 @@ +<!doctype html> +<html class="no-js" lang="en"> + <head> + <meta charset="utf-8" /> + <meta name="viewport" content="width=device-width, initial-scale=1.0" /> + <title>Chat Demo | Ice for JavaScript</title> + <!-- Bundle with all the stylesheets used to build the user interface, + see assets/Makefile in your distribution for details --> + <link rel="stylesheet" type="text/css" href="../../assets/common.css" /> + <link rel="icon" type="image/x-icon" href="../../assets/favicon.ico"> + </head> + <body> + <!-- Header section that contains title and navigation bar --> + <section id="header"> + <nav class="top-bar" data-topbar> + <ul class="title-area"> + <li class="name"> + <h1><a href="../../index.html">Ice for JavaScript</a></h1> + </li> + <li class="toggle-topbar menu-icon"><a href="#">Menu</a></li> + </ul> + <section class="top-bar-section"> + <!-- Right Nav Section --> + <ul class="right"> + <li class="divider"></li> + <li><a href="#" id="viewReadme">Readme</a></li> + <li><a href="#" id="viewSource">Source</a></li> + </ul> + </section> + </nav> + <ul class="breadcrumbs"> + <li><a href="../../index.html">Ice</a></li> + <li><a href="../index.html">Demos</a></li> + <li class="current"><a href="#">Chat Demo</a></li> + </ul> + </section> + <!-- Main section that contains the user interface --> + <section role="main" id="body"> + <!-- Sign In Form --> + <div class="row" id="signin-form"> + <div class="large-12 medium-12 columns"> + <form> + <div class="row"> + <div class="small-4 medium-3 columns"> + <label class="right inline" for="username">Username:</label> + </div> + <div class="small-8 medium-9 columns"> + <input type="text" id="username"/> + </div> + </div> + <div class="row"> + <div class="small-4 medium-3 columns"> + <label class="right inline" for="password">Password:</label> + </div> + <div class="small-8 medium-9 columns"> + <input type="password" id="password"/> + </div> + </div> + <div class="row"> + <div class="small-12 columns"> + <a href="#" class="button small right" id="signin">Sign in</a> + </div> + </div> + </form> + </div> + </div> + <!-- Error Alert --> + <div class="row" style="display:none;opacity:0;" id="signin-alert"> + <div class="large-12 medium-12 columns"> + <div data-alert class="alert-box warning round"> + <span class="error-message"></span> + </div> + </div> + </div> + <!-- Loading Indicator --> + <div class="row" id="loading" style="display:none;opacity:0;"> + <div class="large-12 medium-12 columns"> + <div class="panel"> + <h3>Loading Please Wait...</h3> + <div class="progress radius round"> + <span class="meter" style="width:0%"></span> + </div> + </div> + </div> + </div> + <!-- Chat Form --> + <div class="row" id="chat-form" style="display:none;opacity:0;"> + <div class="large-12 medium-12 columns"> + <nav class="top-bar" data-topbar> + <ul class="title-area"> + <li class="name"> + <h1><a href="#">Chat Demo</a></h1> + </li> + <li class="toggle-topbar menu-icon"><a href="#">Menu</a></li> + </ul> + <section class="top-bar-section"> + <!-- Right Nav Section --> + <ul class="right"> + <li class="divider"></li> + <li class="has-form"> + <a href="#" id="signout" class="button">Sign out</a> + </li> + </ul> + </section> + </nav> + <form> + <div class="row"> + <div class="large-2 columns"> + <ul id="users" class="side-nav"></ul> + </div> + <div class="large-10 columns"> + <textarea id="output" class="disabled" readonly></textarea> + </div> + </div> + <div class="row"> + <div class="large-12 columns"> + <input type="text" id="input" autocomplete="off"/> + </div> + </div> + </form> + </div> + </div> + </section> + <!-- Modal dialog to show the client README --> + <div id="readme-modal" class="reveal-modal" data-reveal> + <h4>Chat Demo Readme</h4> + <hr/> + <p>This demo implements a push client for the + <a href="http://www.zeroc.com/chat/index.html">ZeroC's Chat Demo Application</a>. You can use the + <a href="#" class="chatbutton">Live Client</a> if you don't want to setup your own server. + </p> + + <p>To set up the server follow the instructions from the + <a href="http://www.zeroc.com/chat/download.html">Chat Demo Distribution</a>.</p> + + <p>You will need to update the Glacier2 configuration to include WSS endpoints. + Edit <code>ChatDemo-1.4.0/config/config.glacier2router</code> + and update the <code>Glacier2.Client.Endpoints</code> property with the value shown below:</p> + <p> + <code style="color:#858585;font-weight:normal;font-size:80%;"> + Glacier2.Client.Endpoints=ssl -p 4064 -t 10000 -h 127.0.0.1:tcp -p 4502 -t 10000 -h 127.0.0.1:wss -p 5064 -t 10000 -h 127.0.0.1 + </code> + </p> + <p>You also need to enable the Web Socket transport plug-in. Add the following lines + to <code>ChatDemo-1.4.0/config/config.glacier2router</code>:</p> + <p> + <code style="color:#858585;font-weight:normal;font-size:80%;"> + Ice.Plugin.IceWS=IceWS:createIceWS + </code> + </p> + + <p>After making those modifications to the Glacier2 router configuration, you can start the Chat Demo + server and Glacier2 router as documented in the Chat Demo distribution.</p> + + <div class="panel callout radius"> + <p>You must configure your environment to run IceWS applications as documented in the Ice for JavaScript + <a href="http://doc.zeroc.com/display/Rel/Ice+for+JavaScript+0.1.0+Release+Notes">Release Notes</a>.</p> + </div> + + <p>Once you have configured and started the Chat Demo server and router, + you can log into the chat using the sign-in form below.</p> + + <h4>Using the minified scripts</h4> + <p>When the demo is built with optimizations enabled, it creates a minified + script <code>browser/Client.min.js</code> that includes: + </p> + <ul> + <li>Ice.js (The Ice run-time library)</li> + <li>Glacier2.js (The Glacier2 library)</li> + <li>Chat.js & ChatSession.js (The generated code for this demo)</li> + <li>Client.js (The client application)</li> + </ul> + <p>To use the minified version you should edit the <code>demo/ChatDemo/index.html</code> + file and comment out the non-optimized scripts:</p> + <pre> + <!-- Scripts used during development, for optimized builds + comment the following scripts and uncomment browser/Client.min.js + below --> + <!-- Ice.js (Ice run-time library) --> + <script type="text/javascript" src="../../../lib/Ice.js"></script> + <!-- Glacier2.js (Glacier2 run-time library) --> + <script type="text/javascript" src="../../../lib/Glacier2.js"></script> + <!-- Chat.js (Demo generated code) --> + <script type="text/javascript" src="Chat.js"></script> + <!-- ChatSession.js (Demo generated code) --> + <script type="text/javascript" src="ChatSession.js"></script> + <!-- Client.js (Chat Demo Application) --> + <script type="text/javascript" src="Client.js"></script> + </pre> + <p>Then uncomment the script tag for the minified version</p> + <pre> + <!-- Uncomment the following script to use a minified version of the + scripts that includes: the Ice and Glacier2 run-time libraries, + the generated code and the demo application. --> + <!--<script src="Client.min.js"></script>--> + </pre> + <a class="close-reveal-modal">×</a> + </div> + <!-- Modal dialog to show the client source code --> + <div id="source-modal" class="reveal-modal" data-reveal> + <a class="close-reveal-modal">×</a> + <dl class="tabs" data-tab> + <dt></dt> + <dd class="active"><a href="#panel2-1">Slice</a></dd> + <dd><a href="#panel2-2">JavaScript</a></dd> + <dd><a href="#panel2-3">HTML</a></dd> + </dl> + <div class="tabs-content"> + <div class="content active" id="panel2-1"> + <h6>File: ChatDemo/Chat.ice</h6> + <pre class="source language-c" data-code="Chat.ice"></pre> + <h6>File: ChatDemo/ChatSession.ice</h6> + <pre class="source language-c" data-code="ChatSession.ice"></pre> + </div> + <div class="content" id="panel2-2"> + <h6>File: ChatDemo/Client.js</h6> + <pre class="source" data-code="Client.js"></pre> + </div> + <div class="content" id="panel2-3"> + <h6>File: ChatDemo/index.html</h6> + <pre class="source" data-code="index.html"></pre> + </div> + </div> + </div> + <!-- Footer section --> + <section id="footer"> + <div class="logo"> + <h4><strong>ZeroC</strong></h4> + </div> + <div class="copyright"> + <h6>© 2014 ZeroC, Inc. All rights reserved.</h6> + </div> + </section> + <!-- Bundle with all the scripts used to build the user interface, + see assets/Makefile in your distribution for details --> + <script type="text/javascript" src="../../assets/common.min.js"></script> + <!-- Scripts used during development, for optimized builds + comment the following scripts and uncomment Client.min.js + below --> + <!-- Ice.js (Ice run-time library) --> + <script type="text/javascript" src="../../lib/Ice.js"></script> + <!-- Glacier2.js (Glacier2 run-time library) --> + <script type="text/javascript" src="../../lib/Glacier2.js"></script> + <!-- Chat.js (Demo generated code) --> + <script type="text/javascript" src="Chat.js"></script> + <!-- ChatSession.js (Demo generated code) --> + <script type="text/javascript" src="ChatSession.js"></script> + <!-- Client.js (Chat Demo Application) --> + <script type="text/javascript" src="Client.js"></script> + <!-- Uncomment the following script to use a minified version of the + scripts that includes: the Ice and Glacier2 run-time libraries, + the generated code and the demo application. --> + <!--<script type="text/javascript" src="Client.min.js"></script>--> + + <script type="text/javascript"> + $(".chatbutton").click( + function(e) + { + window.open("https://demo.zeroc.com/chat/js/index.html", "ChatDemo", + "width=800,height=600,location=no,directories=no,status=yes," + + "menubar=no,scrollbars=yes,resizable=yes,toolbar=no"); + return false; + }); + + if(["http:", "https:"].indexOf(document.location.protocol) !== -1) + { + checkGenerated(["Chat.js"]); + } + </script> + </body> +</html> diff --git a/js/demo/Glacier2/Makefile b/js/demo/Glacier2/Makefile new file mode 100644 index 00000000000..979c51d03cc --- /dev/null +++ b/js/demo/Glacier2/Makefile @@ -0,0 +1,22 @@ +# ********************************************************************** +# +# Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +# +# This copy of Ice is licensed to you under the terms described in the +# ICE_LICENSE file included in this distribution. +# +# ********************************************************************** + +top_srcdir = ../.. + +include $(top_srcdir)/config/Make.rules.js + +SUBDIRS = chat + +$(EVERYTHING):: + @for subdir in $(SUBDIRS); \ + do \ + echo "making $@ in $$subdir"; \ + ( cd $$subdir && $(MAKE) $@ ) || exit 1; \ + done + diff --git a/js/demo/Glacier2/Makefile.mak b/js/demo/Glacier2/Makefile.mak new file mode 100644 index 00000000000..fc205ea40a0 --- /dev/null +++ b/js/demo/Glacier2/Makefile.mak @@ -0,0 +1,19 @@ +# ********************************************************************** +# +# Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +# +# This copy of Ice is licensed to you under the terms described in the +# ICE_LICENSE file included in this distribution. +# +# ********************************************************************** + +top_srcdir = ..\.. + +!include $(top_srcdir)\config\Make.rules.mak.js + +SUBDIRS = chat + +$(EVERYTHING):: + @for %i in ( $(SUBDIRS) ) do \ + @echo "making $@ in %i" && \ + cmd /c "cd %i && $(MAKE) -nologo -f Makefile.mak $@" || exit 1 diff --git a/js/demo/Glacier2/README b/js/demo/Glacier2/README new file mode 100644 index 00000000000..2bfa79fb046 --- /dev/null +++ b/js/demo/Glacier2/README @@ -0,0 +1,5 @@ +Demo in this directory: + +- chat + + An application that shows how to write a Glacier2 chat client. diff --git a/js/demo/Glacier2/build.js b/js/demo/Glacier2/build.js new file mode 100644 index 00000000000..281b6bc8f73 --- /dev/null +++ b/js/demo/Glacier2/build.js @@ -0,0 +1,10 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice is licensed to you under the terms described in the +// ICE_LICENSE file included in this distribution. +// +// ********************************************************************** + +require("../../config/build.js").buildDirectory(__dirname);
\ No newline at end of file diff --git a/js/demo/Glacier2/chat/.gitignore b/js/demo/Glacier2/chat/.gitignore new file mode 100644 index 00000000000..9abbacbfb91 --- /dev/null +++ b/js/demo/Glacier2/chat/.gitignore @@ -0,0 +1 @@ +Chat.js diff --git a/js/demo/Glacier2/chat/Chat.ice b/js/demo/Glacier2/chat/Chat.ice new file mode 100644 index 00000000000..907f1f1b50e --- /dev/null +++ b/js/demo/Glacier2/chat/Chat.ice @@ -0,0 +1,28 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice is licensed to you under the terms described in the +// ICE_LICENSE file included in this distribution. +// +// ********************************************************************** + +#pragma once + +#include <Glacier2/Session.ice> + +module Demo +{ + +interface ChatCallback +{ + void message(string data); +}; + +interface ChatSession extends Glacier2::Session +{ + void setCallback(ChatCallback* callback); + void say(string data); +}; + +}; diff --git a/js/demo/Glacier2/chat/Client.js b/js/demo/Glacier2/chat/Client.js new file mode 100644 index 00000000000..ae47b85bb76 --- /dev/null +++ b/js/demo/Glacier2/chat/Client.js @@ -0,0 +1,273 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice is licensed to you under the terms described in the +// ICE_LICENSE file included in this distribution. +// +// ********************************************************************** + +(function(){ + +require("Ice"); +require("Glacier2"); +require("./Chat"); + +// +// Servant that implements the ChatCallback interface, +// the message operation just writes the received data +// to stdout. +// +var ChatCallbackI = Ice.Class(Demo.ChatCallback, { + message: function(data) + { + console.log(data); + } +}); + +var communicator; + +// +// Destroy communicator on SIGINT so application +// exit cleanly. +// +process.once("SIGINT", function() { + if(communicator) + { + communicator.destroy().finally( + function() + { + process.exit(0); + }); + } +}); + +Ice.Promise.try( + function() + { + // + // Initialize the communicator with Ice.Default.Router property + // set to the chat demo Glacier2 router. + // + var id = new Ice.InitializationData(); + id.properties = Ice.createProperties(); + id.properties.setProperty("Ice.Default.Router", "DemoGlacier2/router:tcp -p 4063 -h localhost"); + communicator = Ice.initialize(id); + + function createSession() + { + return Ice.Promise.try( + function() + { + // + // Get a proxy to the default rotuer and down-cast it to Glacier2.Router + // interface to ensure Glacier2 server is available. + // + var router = communicator.getDefaultRouter(); + var id; + + return Glacier2.RouterPrx.checkedCast(router).then( + function(proxy) + { + router = proxy; + console.log("This demo accepts any user-id / password combination."); + process.stdout.write("user id: "); + return getline(); + } + ).then( + function(str) + { + id = str; + process.stdout.write("password: "); + return getline(); + } + ).then( + function(password) + { + return router.createSession(id, password); + } + ).then( + function(session) + { + return runWithSession(router, Demo.ChatSessionPrx.uncheckedCast(session)); + }, + function(ex) + { + if(ex instanceof Glacier2.PermissionDeniedException) + { + console.log("permission denied:\n" + ex.reason); + return createSession(); + } + else if(ex instanceof Glacier2.CannotCreateSessionException) + { + console.log("cannot create session:\n" + ex.reason); + return createSession(); + } + else + { + throw ex; + } + }); + }); + }; + + function runWithSession(router, session) + { + var p = new Ice.Promise(); + + // + // Get the session timeout, the router client category and + // create the client object adapter. + // + // Use Ice.Promise.all to wait for the completion of all the + // calls. + // + Ice.Promise.all( + router.getSessionTimeout(), + router.getCategoryForClient(), + communicator.createObjectAdapterWithRouter("", router) + ).then( + function(timeoutA, categoryA, adapterA) + { + var timeout = timeoutA[0]; + var category = categoryA[0]; + var adapter = adapterA[0]; + + // + // Call refreshSession in a loop to keep the + // session alive. + // + var refreshSession = function() + { + router.refreshSession().exception( + function(ex) + { + p.fail(ex); + } + ).delay(timeout.toNumber() * 500).then( + function() + { + if(!p.completed()) + { + refreshSession(); + } + }); + }; + refreshSession(); + + // + // Create the ChatCallback servant and add it to the ObjectAdapter. + // + var callback = Demo.ChatCallbackPrx.uncheckedCast( + adapter.add(new ChatCallbackI(), new Ice.Identity("callback", category))); + + // + // Set the chat session callback. + // + return session.setCallback(callback); + } + ).then( + function() + { + // + // The chat function sequantially reads stdin messages + // and send it to server using the session say method. + // + function chat() + { + process.stdout.write("==> "); + return getline().then( + function(msg) + { + if(msg == "/quit") + { + p.succeed(); + } + else if(msg.indexOf("/") == 0) + { + console.log("enter /quit to exit."); + } + else + { + return session.say(msg); + } + } + ).then( + function() + { + if(!p.completed()) + { + return chat(); + } + } + ).exception( + function(ex) + { + p.fail(ex); + }); + } + + // + // Start the chat loop + // + return chat(); + } + ).finally( + function() + { + // + // Destroy the session. + // + return router.destroySession(); + } + ).exception( + function(ex) + { + p.fail(ex); + }); + return p; + } + return createSession(); + } +).finally( + function() + { + // + // Destroy the communicator if required. + // + if(communicator) + { + return communicator.destroy(); + } + } +).then( + function() + { + process.exit(0); + }, + function(ex) + { + // + // Handle any exceptions above. + // + console.log(ex.toString()); + process.exit(1); + }); + +// +// Asynchonously process stdin lines using a promise +// +var getline = function() +{ + var p = new Ice.Promise(); + process.stdin.resume(); + process.stdin.once("data", + function(buffer) + { + process.stdin.pause(); + p.succeed(buffer.toString("utf-8").trim()); + }); + return p; +}; + +}()); diff --git a/js/demo/Glacier2/chat/Makefile b/js/demo/Glacier2/chat/Makefile new file mode 100644 index 00000000000..9505e42c653 --- /dev/null +++ b/js/demo/Glacier2/chat/Makefile @@ -0,0 +1,16 @@ +# ********************************************************************** +# +# Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +# +# This copy of Ice is licensed to you under the terms described in the +# ICE_LICENSE file included in this distribution. +# +# ********************************************************************** + +top_srcdir = ../../.. + +TARGETS = Chat.js + +include $(top_srcdir)/config/Make.rules.js + +SLICE2JSFLAGS := $(SLICE2JSFLAGS) -I$(slicedir) diff --git a/js/demo/Glacier2/chat/Makefile.mak b/js/demo/Glacier2/chat/Makefile.mak new file mode 100644 index 00000000000..1130029200c --- /dev/null +++ b/js/demo/Glacier2/chat/Makefile.mak @@ -0,0 +1,16 @@ +# ********************************************************************** +# +# Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +# +# This copy of Ice is licensed to you under the terms described in the +# ICE_LICENSE file included in this distribution. +# +# ********************************************************************** + +top_srcdir = ..\..\.. + +TARGETS = Chat.js + +!include $(top_srcdir)\config\Make.rules.mak.js + +SLICE2JSFLAGS = $(SLICE2JSFLAGS) -I"$(slicedir)" diff --git a/js/demo/Glacier2/chat/README b/js/demo/Glacier2/chat/README new file mode 100644 index 00000000000..7d2ca351ce1 --- /dev/null +++ b/js/demo/Glacier2/chat/README @@ -0,0 +1,9 @@ +This example demonstrates the use of a Glacier2 session to create a +very simple chat server. + +To run the demo, first follow the instructions from the C++ Glacier2 +chat demo README to start the server. + +In a separate window, start the client: + +$ node Client.js diff --git a/js/demo/Glacier2/chat/browser/Client.js b/js/demo/Glacier2/chat/browser/Client.js new file mode 100644 index 00000000000..7e316897669 --- /dev/null +++ b/js/demo/Glacier2/chat/browser/Client.js @@ -0,0 +1,418 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice is licensed to you under the terms described in the +// ICE_LICENSE file included in this distribution. +// +// ********************************************************************** + +(function(){ + +var Promise = Ice.Promise; +var RouterPrx = Glacier2.RouterPrx; +var ChatSessionPrx = Demo.ChatSessionPrx; +var ChatCallbackPrx = Demo.ChatCallbackPrx; + +// +// Servant that implements the ChatCallback interface. +// The message operation just writes the received data +// to the output textarea. +// +var ChatCallbackI = Ice.Class(Demo.ChatCallback, { + message: function(data) + { + $("#output").val($("#output").val() + data + "\n"); + $("#output").scrollTop($("#output").get(0).scrollHeight); + } +}); + +// +// Chat client state +// +var State = { + Disconnected: 0, + Connecting: 1, + Connected:2 +}; + +var state = State.Disconnected; +var hasError = false; + +var signin = function() +{ + var communicator; + var router; + Promise.try( + function() + { + state = State.Connecting; + // + // Dismiss any previous error message. + // + if(hasError) + { + dismissError(); + } + // + // Transition to loading screen + // + return transition("#signin-form", "#loading"); + } + ).then( + function() + { + // + // Start animating the loading progress bar. + // + startProgress(); + + var hostname = document.location.hostname || "127.0.0.1"; + // + // If the demo is accessed vi https, use a secure (WSS) endpoint, otherwise + // use a non-secure (WS) endpoint. + // + // The web server will act as a reverse proxy for WebSocket connections. This + // facilitates the setup of WSS with self-signed certificates because Firefox + // and Internet Explorer certificate exceptions are only valid for the same + // port and host. + // + var secure = document.location.protocol.indexOf("https") != -1; + var router = secure ? "DemoGlacier2/router:wss -p 9090 -h " + hostname + " -r /chatwss" : + "DemoGlacier2/router:ws -p 8080 -h " + hostname + " -r /chatws"; + + // + // Initialize the communicator with the Ice.Default.Router property + // set to the chat demo Glacier2 router. + // + var id = new Ice.InitializationData(); + id.properties = Ice.createProperties(); + id.properties.setProperty("Ice.Default.Router", router); + communicator = Ice.initialize(id); + + // + // Get a proxy to the Glacier2 router using checkedCast to ensure + // the Glacier2 server is available. + // + return RouterPrx.checkedCast(communicator.getDefaultRouter()); + } + ).then( + function(r) + { + router = r; + + // + // Create a session with the Glacier2 router. + // + return router.createSession($("#username").val(), $("#password").val()); + } + ).then( + function(session) + { + run(communicator, router, ChatSessionPrx.uncheckedCast(session)); + } + ).exception( + function(ex) + { + // + // Handle any exceptions that occurred during session creation. + // + if(ex instanceof Glacier2.PermissionDeniedException) + { + error("permission denied:\n" + ex.reason); + } + else if(ex instanceof Glacier2.CannotCreateSessionException) + { + error("cannot create session:\n" + ex.reason); + } + else if(ex instanceof Ice.ConnectFailedException) + { + error("connection to server failed"); + } + else + { + error(ex.toString()); + } + + if(communicator) + { + communicator.destroy(); + } + }); +}; + +var run = function(communicator, router, session) +{ + // + // The chat promise is used to wait for the completion of chatting + // state. The completion could happen because the user signed out, + // or because an exception was raised. + // + var chat = new Promise(); + + // + // Get the session timeout and the router client category, and + // create the client object adapter. + // + // Use Ice.Promise.all to wait for the completion of all the + // calls. + // + Promise.all( + router.getSessionTimeout(), + router.getCategoryForClient(), + communicator.createObjectAdapterWithRouter("", router) + ).then( + function(timeoutArgs, categoryArgs, adapterArgs) + { + var timeout = timeoutArgs[0]; + var category = categoryArgs[0]; + var adapter = adapterArgs[0]; + + // + // Call refreshSession in a loop to keep the + // session alive. + // + var refreshSession = function() + { + router.refreshSession().exception( + function(ex) + { + chat.fail(ex); + } + ).delay(timeout.toNumber() * 500).then( + function() + { + if(!chat.completed()) + { + refreshSession(); + } + }); + }; + refreshSession(); + + // + // Create the ChatCallback servant and add it to the + // ObjectAdapter. + // + var callback = ChatCallbackPrx.uncheckedCast(adapter.add(new ChatCallbackI(), + new Ice.Identity("callback", category))); + + // + // Set the chat session callback. + // + return session.setCallback(callback); + } + ).then( + function() + { + // + // Stop animating the loading progress bar and + // transition to the chat screen. + // + stopProgress(true); + return transition("#loading", "#chat-form"); + } + ).then( + function() + { + $("#loading .meter").css("width", "0%"); + state = State.Connected; + $("#input").focus(); + + // + // Process input events in the input textbox until the chat + // promise is completed. + // + $("#input").keypress( + function(e) + { + if(!chat.completed()) + { + // + // When the enter key is pressed, we send a new + // message using the session say operation and + // reset the textbox contents. + // + if(e.which === 13) + { + var msg = $(this).val(); + $(this).val(""); + session.say(msg).exception( + function(ex) + { + chat.fail(ex); + }); + return false; + } + } + }); + + // + // Exit the chat loop by accepting the chat + // promise. + // + $("#signout").click( + function() + { + chat.succeed(); + return false; + } + ); + + return chat; + } + ).finally( + function() + { + // + // Reset the input text box and chat output + // textarea. + // + $("#input").val(""); + $("#input").off("keypress"); + $("#signout").off("click"); + $("#output").val(""); + + // + // Destroy the session. + // + return router.destroySession(); + } + ).then( + function() + { + // + // Destroy the communicator and go back to the + // disconnected state. + // + communicator.destroy().finally( + function() + { + transition("#chat-form", "#signin-form").finally( + function() + { + $("#username").focus(); + state = State.Disconnected; + }); + }); + } + ).exception( + function(ex) + { + // + // Handle any exceptions that occurred while running. + // + error(ex); + communicator.destroy(); + }); +}; + +// +// Switch to Disconnected state and display the error +// message. +// +var error = function(message) +{ + stopProgress(false); + hasError = true; + var current = state === State.Connecting ? "#loading" : "#chat-form"; + $("#signin-alert span").text(message); + + // + // Transition the screen + // + transition(current, "#signin-alert").then( + function() + { + $("#loading .meter").css("width", "0%"); + $("#signin-form").css("display", "block").animo({ animation: "flipInX", keep: true }); + state = State.Disconnected; + } + ); +}; + +// +// Do a transition from "from" screen to "to" screen, return +// a promise that allows us to wait for the transition +// to complete. If to screen is undefined just animate out the +// from screen. +// +var transition = function(from, to) +{ + var p = new Ice.Promise(); + + $(from).animo({ animation: "flipOutX", keep: true }, + function() + { + $(from).css("display", "none"); + if(to) + { + $(to).css("display", "block").animo({ animation: "flipInX", keep: true }, + function() + { + p.succeed(); + }); + } + else + { + p.succeed(); + } + }); + return p; +}; + +// +// Event handler for Sign in button +// +$("#signin").click(function() + { + signin(); + return false; + }); + +// +// Dismiss error message. +// +function dismissError() +{ + transition("#signin-alert"); + hasError = false; + return false; +}; + +// +// Animate the loading progress bar. +// +var w = 0; +var progress; + +var startProgress = function() +{ + if(!progress) + { + progress = setInterval( + function() + { + w = w === 100 ? 0 : w + 5; + $("#loading .meter").css("width", w.toString() + "%"); + }, + 20); + } +}; + +var stopProgress = function(completed) +{ + if(progress) + { + clearInterval(progress); + progress = null; + if(completed) + { + $("#loading .meter").css("width", "100%"); + } + } +}; + +$("#username").focus(); + +}()); diff --git a/js/demo/Glacier2/chat/build.js b/js/demo/Glacier2/chat/build.js new file mode 100644 index 00000000000..021f1550ff1 --- /dev/null +++ b/js/demo/Glacier2/chat/build.js @@ -0,0 +1,10 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice is licensed to you under the terms described in the +// ICE_LICENSE file included in this distribution. +// +// ********************************************************************** + +require ("../../../config/build").build(__dirname, ["Chat.ice"]); diff --git a/js/demo/Glacier2/chat/expect.py b/js/demo/Glacier2/chat/expect.py new file mode 100755 index 00000000000..45ef1189b50 --- /dev/null +++ b/js/demo/Glacier2/chat/expect.py @@ -0,0 +1,73 @@ +#!/usr/bin/env python +# ********************************************************************** +# +# Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +# +# This copy of Ice is licensed to you under the terms described in the +# ICE_LICENSE file included in this distribution. +# +# ********************************************************************** + +import sys, os, signal + +path = [ ".", "..", "../..", "../../..", "../../../.." ] +head = os.path.dirname(sys.argv[0]) +if len(head) > 0: + path = [os.path.join(head, p) for p in path] +path = [os.path.abspath(p) for p in path if os.path.exists(os.path.join(p, "demoscript")) ] +if len(path) == 0: + raise RuntimeError("can't find toplevel directory!") +sys.path.append(path[0]) + +from demoscript import Util + +server = Util.spawn('./server --Ice.PrintAdapterReady', Util.getMirrorDir("cpp"), mapping="cpp") +server.expect('.* ready') + +glacier2 = Util.spawn(Util.getGlacier2Router() + ' --Ice.Config=%s/config.glacier2 --Ice.PrintAdapterReady' % Util.getMirrorDir("cpp")) +glacier2.expect('Glacier2.Client ready') +glacier2.expect('Glacier2.Server ready') + +sys.stdout.write("starting client 1... ") +sys.stdout.flush() +client1 = Util.spawn('node Client.js') +client1.expect('user id:') +client1.sendline("foo") +client1.expect('password:') +client1.sendline("foo") +print("ok") + +sys.stdout.write("starting client 2... ") +sys.stdout.flush() +client2 = Util.spawn('node Client.js') +client2.expect('user id:') +client2.sendline("bar") +client2.expect('password:') +client2.sendline("bar") + +client1.expect("bar has entered the chat room") +print("ok") + +sys.stdout.write("testing chat... ") +sys.stdout.flush() +client1.sendline("hi") +client1.expect("foo says: hi") +client2.expect("foo says: hi") + +client2.sendline("hello") +client2.expect("bar says: hello") +client1.expect("bar says: hello") + +client1.sendline("/quit") +client1.waitTestSuccess() +client2.expect("foo has left the chat room") + +client2.sendline("/quit") +client2.waitTestSuccess() +print("ok") + +server.kill(signal.SIGINT) +server.waitTestSuccess() + +glacier2.kill(signal.SIGINT) +glacier2.waitTestSuccess() diff --git a/js/demo/Glacier2/chat/index.html b/js/demo/Glacier2/chat/index.html new file mode 100644 index 00000000000..18278b4c66c --- /dev/null +++ b/js/demo/Glacier2/chat/index.html @@ -0,0 +1,189 @@ +<!doctype html> +<html class="no-js" lang="en"> + <head> + <meta charset="utf-8" /> + <meta name="viewport" content="width=device-width, initial-scale=1.0" /> + <title>Chat Demo | Ice for JavaScript</title> + <!-- Bundle with all the stylesheets used to build the user interface, + see assets/Makefile in your distribution for details --> + <link rel="stylesheet" type="text/css" href="../../../assets/common.css" /> + <link rel="icon" type="image/x-icon" href="../../../assets/favicon.ico"> + </head> + <body> + <!-- Header section that contains title and navigation bar --> + <section id="header"> + <nav class="top-bar" data-topbar> + <ul class="title-area"> + <li class="name"> + <h1><a href="../../../index.html">Ice for JavaScript</a></h1> + </li> + <li class="toggle-topbar menu-icon"><a href="#">Menu</a></li> + </ul> + <section class="top-bar-section"> + <!-- Right Nav Section --> + <ul class="right"> + <li class="divider"></li> + <li><a href="#" id="viewReadme">Readme</a></li> + <li><a href="#" id="viewSource">Source</a></li> + </ul> + </section> + </nav> + <ul class="breadcrumbs"> + <li><a href="../../../index.html">Ice</a></li> + <li><a href="../../index.html">Demos</a></li> + <li class="current"><a href="#">Glacier2</a></li> + <li class="current"><a href="#">Chat</a></li> + </ul> + </section> + <!-- Main section that contains the user interface --> + <section role="main" id="body"> + <!-- Sign In Form --> + <div class="row" id="signin-form"> + <div class="large-12 medium-12 columns"> + <form> + <div class="row"> + <div class="small-4 medium-3 columns"> + <label class="right inline" for="username">Username:</label> + </div> + <div class="small-8 medium-9 columns"> + <input type="text" id="username"/> + </div> + </div> + <div class="row"> + <div class="small-4 medium-3 columns"> + <label class="right inline" for="password">Password:</label> + </div> + <div class="small-8 medium-9 columns"> + <input type="password" id="password"/> + </div> + </div> + <div class="row"> + <div class="small-12 columns"> + <a href="#" class="button small right" id="signin">Sign in</a> + </div> + </div> + </form> + </div> + </div> + <!-- Error Alert --> + <div class="row" style="display:none;opacity:0;" id="signin-alert"> + <div class="large-12 medium-12 columns"> + <div data-alert class="alert-box warning round"> + <span class="error-message"></span> + </div> + </div> + </div> + <!-- Loading Indicator --> + <div class="row" id="loading" style="display:none;opacity:0;"> + <div class="large-12 medium-12 columns"> + <div class="panel"> + <h3>Loading Please Wait...</h3> + <div class="progress radius round"> + <span class="meter" style="width:0%"></span> + </div> + </div> + </div> + </div> + <!-- Chat Form --> + <div class="row" id="chat-form" style="display:none;opacity:0;"> + <div class="large-12 medium-12 columns"> + <nav class="top-bar" data-topbar> + <ul class="title-area"> + <li class="name"> + <h1><a href="#">Chat</a></h1> + </li> + <li class="toggle-topbar menu-icon"><a href="#">Menu</a></li> + </ul> + <section class="top-bar-section"> + <!-- Right Nav Section --> + <ul class="right"> + <li class="divider"></li> + <li class="has-form"> + <a href="#" id="signout" class="button">Sign out</a> + </li> + </ul> + </section> + </nav> + <form> + <textarea id="output" class="disabled" readonly></textarea> + <input type="text" id="input" autocomplete="off"/> + </form> + </div> + </div> + </section> + <!-- Modal dialog to show the client README --> + <div id="readme-modal" class="reveal-modal medium" data-reveal> + <h4>Chat Demo Readme</h4> + <hr/> + <p>This example demonstrates the use of a Glacier2 session to create a + very simple chat client.</p> + + <p>First follow the instructions from the C++ Glacier2 chat demo README to + start the server.</p> + <div class="panel callout radius"> + <ul> + <li>To use the C++ server you'll need a C++ compiler compatible with your + Ice for JavaScript distribution.</li> + </ul> + </div> + + <p>Once the chat server is ready you can sign in using any username + and password.</p> + <div class="panel callout radius"> + <p>The client is configured to use WSS secure endpoints when the page + is loaded over HTTPS and WS unsecure endpoints when loaded over HTTP.</p> + </div> + <a class="close-reveal-modal">×</a> + </div> + <!-- Modal dialog to show the client source code --> + <div id="source-modal" class="reveal-modal" data-reveal> + <a class="close-reveal-modal">×</a> + <dl class="tabs" data-tab> + <dt></dt> + <dd class="active"><a href="#panel2-1">Slice</a></dd> + <dd><a href="#panel2-2">JavaScript</a></dd> + <dd><a href="#panel2-3">HTML</a></dd> + </dl> + <div class="tabs-content"> + <div class="content active" id="panel2-1"> + <h6>File: Glacier2/chat/Chat.ice</h6> + <pre class="source language-c" data-code="Chat.ice"></pre> + </div> + <div class="content" id="panel2-2"> + <h6>File: Glacier2/chat/browser/Client.js</h6> + <pre class="source" data-code="browser/Client.js"></pre> + </div> + <div class="content" id="panel2-3"> + <h6>File: Glacier2/chat/index.html</h6> + <pre class="source" data-code="index.html"></pre> + </div> + </div> + </div> + <!-- Footer section --> + <section id="footer"> + <div class="logo"> + <h4><strong>ZeroC</strong></h4> + </div> + <div class="copyright"> + <h6>© 2014 ZeroC, Inc. All rights reserved.</h6> + </div> + </section> + <!-- Bundle with all the scripts used to build the user interface, + see assets/Makefile in your distribution for details --> + <script type="text/javascript" src="../../../assets/common.min.js"></script> + <!-- Ice.js (Ice run-time library) --> + <script type="text/javascript" src="../../../lib/Ice.js"></script> + <!-- Glacier2.js (Glacier2 client run-time library) --> + <script type="text/javascript" src="../../../lib/Glacier2.js"></script> + <!-- Chat.js (Demo generated code) --> + <script type="text/javascript" src="Chat.js"></script> + <!-- browser/Client.js (Chat Demo Application) --> + <script type="text/javascript" src="browser/Client.js"></script> + <script type="text/javascript"> + if(["http:", "https:"].indexOf(document.location.protocol) !== -1) + { + checkGenerated(["Chat.js"]); + } + </script> + </body> +</html> diff --git a/js/demo/Ice/Makefile b/js/demo/Ice/Makefile new file mode 100644 index 00000000000..57a89792ae9 --- /dev/null +++ b/js/demo/Ice/Makefile @@ -0,0 +1,26 @@ +# ********************************************************************** +# +# Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +# +# This copy of Ice is licensed to you under the terms described in the +# ICE_LICENSE file included in this distribution. +# +# ********************************************************************** + +top_srcdir = ../.. + +include $(top_srcdir)/config/Make.rules.js + +SUBDIRS = hello \ + latency \ + minimal \ + throughput \ + bidir + +$(EVERYTHING):: + @for subdir in $(SUBDIRS); \ + do \ + echo "making $@ in $$subdir"; \ + ( cd $$subdir && $(MAKE) $@ ) || exit 1; \ + done + diff --git a/js/demo/Ice/Makefile.mak b/js/demo/Ice/Makefile.mak new file mode 100644 index 00000000000..7ca44e306ff --- /dev/null +++ b/js/demo/Ice/Makefile.mak @@ -0,0 +1,23 @@ +# ********************************************************************** +# +# Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +# +# This copy of Ice is licensed to you under the terms described in the +# ICE_LICENSE file included in this distribution. +# +# ********************************************************************** + +top_srcdir = ..\.. + +!include $(top_srcdir)\config\Make.rules.mak.js + +SUBDIRS = hello \ + latency \ + minimal \ + throughput \ + bidir + +$(EVERYTHING):: + @for %i in ( $(SUBDIRS) ) do \ + @echo "making $@ in %i" && \ + cmd /c "cd %i && $(MAKE) -nologo -f Makefile.mak $@" || exit 1 diff --git a/js/demo/Ice/README b/js/demo/Ice/README new file mode 100644 index 00000000000..b6696abfa34 --- /dev/null +++ b/js/demo/Ice/README @@ -0,0 +1,27 @@ +Demos in this directory: + +- bidir + + This demo shows how to use bidirectional connections for callbacks. + +- hello + + This demo illustrates how to invoke ordinary (twoway) operations, as + well as how to invoke oneway operations, use datagrams, secure + invocations, and how to use batched invocations. + +- latency + + A simple latency test that measures the basic call dispatch delay of + Ice. + +- minimal + + This demo illustrates a minimal Ice application. + +- throughput + + A simple throughput demo that allows you to send sequences of + various types between client and server and to measure the maximum + bandwidth that can be achieved using serialized synchronous + requests. diff --git a/js/demo/Ice/bidir/.gitignore b/js/demo/Ice/bidir/.gitignore new file mode 100644 index 00000000000..d9d905e483c --- /dev/null +++ b/js/demo/Ice/bidir/.gitignore @@ -0,0 +1 @@ +Callback.js diff --git a/js/demo/Ice/bidir/Callback.ice b/js/demo/Ice/bidir/Callback.ice new file mode 100644 index 00000000000..e985dd9919a --- /dev/null +++ b/js/demo/Ice/bidir/Callback.ice @@ -0,0 +1,27 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice is licensed to you under the terms described in the +// ICE_LICENSE file included in this distribution. +// +// ********************************************************************** + +#pragma once + +#include <Ice/Identity.ice> + +module Demo +{ + +interface CallbackReceiver +{ + void callback(int num); +}; + +interface CallbackSender +{ + void addClient(Ice::Identity ident); +}; + +}; diff --git a/js/demo/Ice/bidir/Client.js b/js/demo/Ice/bidir/Client.js new file mode 100644 index 00000000000..9dbfaff65ee --- /dev/null +++ b/js/demo/Ice/bidir/Client.js @@ -0,0 +1,109 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice is licensed to you under the terms described in the +// ICE_LICENSE file included in this distribution. +// +// ********************************************************************** + +(function(){ + +require("Ice"); +require("./Callback"); + +var Demo = global.Demo; +var CallbackSenderPrx = Demo.CallbackSenderPrx; + +// +// Define a servant class that implements Demo.CallbackReceiver +// interface. +// +var CallbackReceiverI = Ice.Class(Demo.CallbackReceiver, { + callback: function(num, current) + { + console.log("received callback #" + num); + } +}); + +var id = new Ice.InitializationData(); +id.properties = Ice.createProperties(); +// +// Client-side ACM must be disabled for bidirectional connections. +// +id.properties.setProperty("Ice.ACM.Client", "0"); + +var communicator = Ice.initialize(id); + +// +// Exit on SIGINT +// +process.on("SIGINT", function() { + if(communicator) + { + communicator.destroy().finally( + function() + { + process.exit(0); + }); + } +}); + +Ice.Promise.try( + function() + { + // + // Initialize the communicator and create a proxy to the sender object. + // + var proxy = communicator.stringToProxy("sender:tcp -p 10000"); + + // + // Down-cast the proxy to the Demo.CallbackSender interface. + // + return CallbackSenderPrx.checkedCast(proxy).then( + function(server) + { + // + // Create the client object adapter. + // + return communicator.createObjectAdapter("").then( + function(adapter) + { + // + // Create a callback receiver servant and add it to + // the object adapter. + // + var r = adapter.addWithUUID(new CallbackReceiverI()); + + // + // Set the connection adapter. + // + proxy.ice_getCachedConnection().setAdapter(adapter); + + // + // Register the client with the bidir server. + // + return server.addClient(r.ice_getIdentity()); + }); + }); + } +).exception( + function(ex) + { + console.log(ex.toString()); + Promise.try( + function() + { + if(communicator) + { + return communicator.destroy(); + } + } + ).finally( + function() + { + process.exit(1); + }); + }); + +}()); diff --git a/js/demo/Ice/bidir/Makefile b/js/demo/Ice/bidir/Makefile new file mode 100644 index 00000000000..8a729de6c0f --- /dev/null +++ b/js/demo/Ice/bidir/Makefile @@ -0,0 +1,16 @@ +# ********************************************************************** +# +# Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +# +# This copy of Ice is licensed to you under the terms described in the +# ICE_LICENSE file included in this distribution. +# +# ********************************************************************** + +top_srcdir = ../../.. + +TARGETS = Callback.js + +include $(top_srcdir)/config/Make.rules.js + +SLICE2JSFLAGS := $(SLICE2JSFLAGS) -I$(slicedir) diff --git a/js/demo/Ice/bidir/Makefile.mak b/js/demo/Ice/bidir/Makefile.mak new file mode 100644 index 00000000000..4163feef92d --- /dev/null +++ b/js/demo/Ice/bidir/Makefile.mak @@ -0,0 +1,16 @@ +# ********************************************************************** +# +# Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +# +# This copy of Ice is licensed to you under the terms described in the +# ICE_LICENSE file included in this distribution. +# +# ********************************************************************** + +top_srcdir = ..\..\.. + +TARGETS = Callback.js + +!include $(top_srcdir)\config\Make.rules.mak.js + +SLICE2JSFLAGS = $(SLICE2JSFLAGS) -I"$(slicedir)" diff --git a/js/demo/Ice/bidir/README b/js/demo/Ice/bidir/README new file mode 100644 index 00000000000..85e5e1247f8 --- /dev/null +++ b/js/demo/Ice/bidir/README @@ -0,0 +1,23 @@ +This demo shows how to use bidirectional connections for callbacks. +This is typically used if the server cannot open a connection to the +client to send callbacks, for example, because firewalls block +incoming connections to the client. + +To run the demo, first you need to start the Ice bidir server. This +distribution includes server implementations in Python and C++, and +each one has its own README file with instructions for starting the +server. Please refer to the Python or C++ README in the appropriate +demo subdirectory for more information. + +Note: + + * To use the Python server you'll need a Python installation that is + compatible with the Ice for Python module included in Ice 3.5.1. + + * To use the C++ server you'll need a C++ compiler compatible with + the Ice 3.5.1 C++ distribution. + +After starting the server, open a separate window and start the +client: + +$ node Client.js diff --git a/js/demo/Ice/bidir/browser/Client.js b/js/demo/Ice/bidir/browser/Client.js new file mode 100644 index 00000000000..dd0b340d8d0 --- /dev/null +++ b/js/demo/Ice/bidir/browser/Client.js @@ -0,0 +1,224 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice is licensed to you under the terms described in the +// ICE_LICENSE file included in this distribution. +// +// ********************************************************************** + +(function(){ + +var Promise = Ice.Promise; +var CallbackSenderPrx = Demo.CallbackSenderPrx; + +// +// Define a servant class that implements the Demo.CallbackReceiver +// interface. +// +var CallbackReceiverI = Ice.Class(Demo.CallbackReceiver, { + callback: function(num, current) + { + writeLine("received callback #" + num); + } +}); + +var id = new Ice.InitializationData(); +id.properties = Ice.createProperties(); +// +// Client-side ACM must be disabled for bidirectional connections. +// +id.properties.setProperty("Ice.ACM.Client", "0"); + +// +// Initialize the communicator +// +var communicator = Ice.initialize(id); + +var connection; + +var start = function() +{ + // + // Create a proxy to the sender object. + // + var hostname = document.location.hostname || "127.0.0.1"; + var proxy = communicator.stringToProxy("sender:ws -p 10002 -h " + hostname); + + // + // Down-cast the proxy to the Demo.CallbackSender interface. + // + return CallbackSenderPrx.checkedCast(proxy).then( + function(server) + { + // + // Create the client object adapter. + // + return communicator.createObjectAdapter("").then( + function(adapter) + { + // + // Create a callback receiver servant and add it to + // the object adapter. + // + var r = adapter.addWithUUID(new CallbackReceiverI()); + + // + // Set the connection adapter and remember the connection. + // + connection = proxy.ice_getCachedConnection(); + connection.setAdapter(adapter); + + // + // Register the client with the bidir server. + // + return server.addClient(r.ice_getIdentity()); + }); + }); +}; + +var stop = function() +{ + // + // Close the connection, the server will unregister the client + // when it tries to invoke on the bi-dir proxy. + // + return connection.close(false); +} + +// +// Setup button click handlers +// +$("#start").click( + function() + { + if(isDisconnected()) + { + setState(State.Connecting); + Promise.try( + function() + { + return start().then(function() + { + setState(State.Connected); + }); + } + ).exception( + function(ex) + { + $("#output").val(ex.toString()); + setState(State.Disconnected); + } + ); + } + return false; + }); + +$("#stop").click( + function() + { + if(isConnected()) + { + setState(State.Disconnecting); + Promise.try( + function() + { + return stop(); + } + ).exception( + function(ex) + { + $("#output").val(ex.toString()); + } + ).finally( + function() + { + setState(State.Disconnected); + } + ); + } + return false; + }); + +// +// Handle client state +// +var State = { + Disconnected: 0, + Connecting: 1, + Connected: 2, + Disconnecting: 3 +}; + +var isConnected = function() +{ + return state == State.Connected; +}; + +var isDisconnected = function() +{ + return state == State.Disconnected; +}; + +var writeLine = function(msg) +{ + $("#output").val($("#output").val() + msg + "\n"); + $("#output").scrollTop($("#output").get(0).scrollHeight); +} + +var state; + +var setState = function(s) +{ + if(state == s) + { + return; + } + state = s; + switch(s) + { + case State.Disconnected: + { + $("#start").removeClass("disabled"); + + $("#progress").hide(); + $("body").removeClass("waiting"); + break; + } + case State.Connecting: + { + $("#output").val(""); + $("#start").addClass("disabled"); + + $("#progress .message").text("Connecting..."); + $("#progress").show(); + $("body").addClass("waiting"); + break; + } + case State.Connected: + { + $("#stop").removeClass("disabled"); + + $("#progress").hide(); + $("body").removeClass("waiting"); + break; + } + case State.Disconnecting: + { + $("#stop").addClass("disabled"); + + $("#progress .message").text("Disconnecting..."); + $("#progress").show(); + $("body").addClass("waiting"); + break; + } + default: + { + break; + } + } +}; + +setState(State.Disconnected); + +}()); diff --git a/js/demo/Ice/bidir/build.js b/js/demo/Ice/bidir/build.js new file mode 100644 index 00000000000..4047419892c --- /dev/null +++ b/js/demo/Ice/bidir/build.js @@ -0,0 +1,10 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice is licensed to you under the terms described in the +// ICE_LICENSE file included in this distribution. +// +// ********************************************************************** + +require ("../../../config/build").build(__dirname, ["Callback.ice"]);
\ No newline at end of file diff --git a/js/demo/Ice/bidir/expect.py b/js/demo/Ice/bidir/expect.py new file mode 100755 index 00000000000..ff420b2f2e3 --- /dev/null +++ b/js/demo/Ice/bidir/expect.py @@ -0,0 +1,30 @@ +#!/usr/bin/env python +# ********************************************************************** +# +# Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +# +# This copy of Ice is licensed to you under the terms described in the +# ICE_LICENSE file included in this distribution. +# +# ********************************************************************** + +import sys, os + +path = [ ".", "..", "../..", "../../..", "../../../.." ] +head = os.path.dirname(sys.argv[0]) +if len(head) > 0: + path = [os.path.join(head, p) for p in path] +path = [os.path.abspath(p) for p in path if os.path.exists(os.path.join(p, "demoscript")) ] +if len(path) == 0: + raise RuntimeError("can't find toplevel directory!") +sys.path.append(path[0]) + +from demoscript import Util +from demoscript.Ice import bidir + +server = Util.spawn('./server --Ice.PrintAdapterReady --Ice.Warn.Connections=0', Util.getMirrorDir("cpp"), mapping="cpp") +server.expect('.* ready') + +client = 'node Client.js --Ice.Warn.Connections=0' + +bidir.run(client, server) diff --git a/js/demo/Ice/bidir/index.html b/js/demo/Ice/bidir/index.html new file mode 100644 index 00000000000..f681598d0de --- /dev/null +++ b/js/demo/Ice/bidir/index.html @@ -0,0 +1,162 @@ +<!doctype html> +<html class="no-js" lang="en"> + <head> + <meta charset="utf-8" /> + <meta name="viewport" content="width=device-width, initial-scale=1.0" /> + <title>Bidir Demo | Ice for JavaScript</title> + <!-- Bundle with all the stylesheets used to build the user interface, + see assets/Makefile in your distribution for details --> + <link rel="stylesheet" type="text/css" href="../../../assets/common.css" /> + <link rel="icon" type="image/x-icon" href="../../../assets/favicon.ico"> + </head> + <body> + <!-- Header section that contains title and navigation bar --> + <section id="header"> + <nav class="top-bar" data-topbar> + <ul class="title-area"> + <li class="name"> + <h1><a href="../../../index.html">Ice for JavaScript</a></h1> + </li> + <li class="toggle-topbar menu-icon"><a href="#">Menu</a></li> + </ul> + <section class="top-bar-section"> + <!-- Right Nav Section --> + <ul class="right"> + <li class="divider"></li> + <li><a href="#" id="viewReadme">Readme</a></li> + <li><a href="#" id="viewSource" class="disabled">Source</a></li> + </ul> + </section> + </nav> + <ul class="breadcrumbs"> + <li><a href="../../../index.html">Ice</a></li> + <li><a href="../../index.html">Demos</a></li> + <li class="current"><a href="#">Bidir</a></li> + </ul> + </section> + <!-- Main section that contains the user interface --> + <section role="main" id="body"> + <div class="row"> + <div class="large-12 medium-12 columns"> + <form> + <a href="#" class="button small" id="start">Start</a> + <a href="#" class="button small disabled" id="stop">Stop</a> + <textarea id="output" class="disabled" readonly></textarea> + <div id="progress" class="row hide"> + <div class="small-12 columns left"> + <div class="inline left icon"></div> + <div class="text"></div> + </div> + </div> + </form> + </div> + </div> + </section> + <!-- Modal dialog to show the client README --> + <div id="readme-modal" class="reveal-modal medium" data-reveal> + <h4>Bidir Demo Readme</h4> + <hr/> + <p>This demo shows how to use bidirectional connections for callbacks.</p> + <p>This is typically used if the server cannot open a connection to the + client to send callbacks, for example, because firewalls block + incoming connections to the client.</p> + + <p>To run the demo, first you need to start the Ice bidir server. This + distribution includes server implementations in Python and C++, and + each one has its own README file with instructions for starting the + server. Please refer to the Python or C++ README in the appropriate + demo subdirectory for more information. + </p> + + <div class="panel callout radius"> + <ul> + <li>To use the Python server you'll need a Python installation that is + compatible with the Ice for Python module included in Ice 3.5.1.</li> + + <li>To use the C++ server you'll need a C++ compiler compatible with your + Ice for JavaScript distribution.</li> + </ul> + </div> + + <p>Then you can use the <strong>Start</strong> and <strong>Stop</strong> buttons to + add or remove a callback to the server, respectively.</p> + + <a class="close-reveal-modal">×</a> + </div> + <!-- Modal dialog to show the client source code --> + <div id="source-modal" class="reveal-modal" data-reveal> + <a class="close-reveal-modal">×</a> + <dl class="tabs" data-tab> + <dt></dt> + <dd class="active"><a href="#panel2-1">Slice</a></dd> + <dd><a href="#panel2-2">JavaScript</a></dd> + <dd><a href="#panel2-3">HTML</a></dd> + </dl> + <div class="tabs-content"> + <div class="content active" id="panel2-1"> + <h6>File: demo/Ice/bidir/Callback.ice</h6> + <pre class="source language-c" data-code="Callback.ice"></pre> + </div> + <div class="content" id="panel2-2"> + <h6>File: demo/Ice/bidir/browser/Client.js</h6> + <pre class="source" data-code="browser/Client.js"></pre> + </div> + <div class="content" id="panel2-3"> + <h6>File: demo/Ice/bidir/index.html</h6> + <pre class="source" data-code="index.html"></pre> + </div> + </div> + </div> + <div id="no-https-modal" class="reveal-modal" data-reveal> + <p>This client uses a non-secure WebSocket connection, but your browser does not allow + the client to make a non-secure connection from a page loaded via HTTPS. You can run the + demo from an HTTP page by navigating to <a href=""></a>. + </p> + </div> + <!-- Footer section --> + <section id="footer"> + <div class="logo"> + <h4><strong>ZeroC</strong></h4> + </div> + <div class="copyright"> + <h6>© 2014 ZeroC, Inc. All rights reserved.</h6> + </div> + </section> + <!-- Bundle with all the scripts used to build the user interface, + see assets/Makefile in your distribution for details --> + <script type="text/javascript" src="../../../assets/common.min.js"></script> + <!-- Ice.js (Ice run-time library) --> + <script type="text/javascript" src="../../../lib/Ice.js"></script> + <!-- Callback.js (Demo generated code) --> + <script type="text/javascript" src="Callback.js"></script> + <!-- browser/Client.js (Bidir Demo Application) --> + <script type="text/javascript" src="browser/Client.js"></script> + <script type="text/javascript"> + // + // Firefox and IE we doesn't allow WS connections from + // HTTPS pages. + // + if(document.location.protocol === "https:" && + (navigator.userAgent.indexOf("MSIE") !== -1 || + navigator.userAgent.indexOf("Firefox") !== -1 || + navigator.userAgent.indexOf("Trident/7.0") !== -1)) + { + var href = "http://" + document.location.hostname + ":8080" + document.location.pathname; + $("#no-https-modal a").attr("href", href); + $("#no-https-modal a").text(href); + $("#no-https-modal").foundation({ + reveal: + { + close_on_background_click: false, + close_on_esc: false + } + }); + $("#no-https-modal").foundation("reveal", "open"); + } + else if(document.location.protocol === "http:") + { + checkGenerated(["Callback.js"]); + } + </script> + </body> +</html> diff --git a/js/demo/Ice/build.js b/js/demo/Ice/build.js new file mode 100644 index 00000000000..281b6bc8f73 --- /dev/null +++ b/js/demo/Ice/build.js @@ -0,0 +1,10 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice is licensed to you under the terms described in the +// ICE_LICENSE file included in this distribution. +// +// ********************************************************************** + +require("../../config/build.js").buildDirectory(__dirname);
\ No newline at end of file diff --git a/js/demo/Ice/hello/.gitignore b/js/demo/Ice/hello/.gitignore new file mode 100644 index 00000000000..48762ead96c --- /dev/null +++ b/js/demo/Ice/hello/.gitignore @@ -0,0 +1 @@ +Hello.js diff --git a/js/demo/Ice/hello/Client.js b/js/demo/Ice/hello/Client.js new file mode 100644 index 00000000000..2d65c23a83e --- /dev/null +++ b/js/demo/Ice/hello/Client.js @@ -0,0 +1,195 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice is licensed to you under the terms described in the +// ICE_LICENSE file included in this distribution. +// +// ********************************************************************** + +(function(){ + +require("Ice"); +require("./Hello"); + +function menu() +{ + process.stdout.write( + "usage:\n" + + "t: send greeting as twoway\n" + + "o: send greeting as oneway\n" + + "O: send greeting as batch oneway\n" + + "f: flush all batch requests\n" + + "T: set a timeout\n" + + "P: set a server delay\n" + + //"S: switch secure mode on/off\n" + + "s: shutdown server\n" + + "x: exit\n" + + "?: help\n" + + "\n"); +} + +var communicator; +Ice.Promise.try( + function() + { + communicator = Ice.initialize(); + var proxy = communicator.stringToProxy("hello:default -p 10000").ice_twoway().ice_timeout(-1).ice_secure(false); + var secure = false; + var timeout = -1; + var delay = 0; + + return Demo.HelloPrx.checkedCast(proxy).then( + function(twoway) + { + var oneway = twoway.ice_oneway(); + var batchOneway = twoway.ice_batchOneway(); + + menu(); + process.stdout.write("==> "); + var loop = new Ice.Promise(); + function processKey(key) + { + if(key == "x") + { + loop.succeed(); + return; + } + + if(key == "t") + { + return twoway.sayHello(delay); + } + else if(key == "o") + { + return oneway.sayHello(delay); + } + else if(key == "O") + { + return batchOneway.sayHello(delay); + } + else if(key == "f") + { + return communicator.flushBatchRequests(); + } + else if(key == "T") + { + if(timeout == -1) + { + timeout = 2000; + } + else + { + timeout = -1; + } + + twoway = twoway.ice_timeout(timeout); + oneway = oneway.ice_timeout(timeout); + batchOneway = batchOneway.ice_timeout(timeout); + + if(timeout == -1) + { + console.log("timeout is now switched off"); + } + else + { + console.log("timeout is now set to 2000ms"); + } + } + else if(key == "P") + { + if(delay === 0) + { + delay = 2500; + } + else + { + delay = 0; + } + + if(delay === 0) + { + console.log("server delay is now deactivated"); + } + else + { + console.log("server delay is now set to 2500ms"); + } + } + else if(key == "s") + { + return twoway.shutdown(); + } + else if(key == "?") + { + process.stdout.write("\n"); + menu(); + } + else + { + console.log("unknown command `" + key + "'"); + process.stdout.write("\n"); + menu(); + } + } + + // + // Process keys sequentially. We chain the promise objects + // returned by processKey(). Once we have process all the + // keys we print the prompt and resume the standard input. + // + process.stdin.resume(); + var promise = new Ice.Promise().succeed(); + process.stdin.on("data", + function(buffer) + { + process.stdin.pause(); + var data = buffer.toString("utf-8").trim().split(""); + // Process each key + data.forEach(function(key) + { + promise = promise.then( + function() + { + return processKey(key); + } + ).exception( + function(ex) + { + console.log(ex.toString()); + }); + }); + // Once we're done, print the prompt + promise.then(function() + { + if(!loop.completed()) + { + process.stdout.write("==> "); + process.stdin.resume(); + } + }); + data = []; + }); + + return loop; + }); + } +).finally( + function() + { + if(communicator) + { + return communicator.destroy(); + } + } +).then( + function() + { + process.exit(0); + }, + function(ex) + { + console.log(ex.toString()); + process.exit(1); + }); +}()); diff --git a/js/demo/Ice/hello/Hello.ice b/js/demo/Ice/hello/Hello.ice new file mode 100644 index 00000000000..28e16b8de3e --- /dev/null +++ b/js/demo/Ice/hello/Hello.ice @@ -0,0 +1,22 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice is licensed to you under the terms described in the +// ICE_LICENSE file included in this distribution. +// +// ********************************************************************** + +#pragma once + +module Demo +{ + +interface Hello +{ + idempotent void sayHello(int delay); + void shutdown(); +}; + +}; + diff --git a/js/demo/Ice/hello/Makefile b/js/demo/Ice/hello/Makefile new file mode 100644 index 00000000000..3d389b91775 --- /dev/null +++ b/js/demo/Ice/hello/Makefile @@ -0,0 +1,16 @@ +# ********************************************************************** +# +# Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +# +# This copy of Ice is licensed to you under the terms described in the +# ICE_LICENSE file included in this distribution. +# +# ********************************************************************** + +top_srcdir = ../../.. + +TARGETS = Hello.js + +include $(top_srcdir)/config/Make.rules.js + +SLICE2JSFLAGS := $(SLICE2JSFLAGS) -I$(slicedir) diff --git a/js/demo/Ice/hello/Makefile.mak b/js/demo/Ice/hello/Makefile.mak new file mode 100644 index 00000000000..dcd0cc79cf8 --- /dev/null +++ b/js/demo/Ice/hello/Makefile.mak @@ -0,0 +1,16 @@ +# ********************************************************************** +# +# Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +# +# This copy of Ice is licensed to you under the terms described in the +# ICE_LICENSE file included in this distribution. +# +# ********************************************************************** + +top_srcdir = ..\..\.. + +TARGETS = Hello.js + +!include $(top_srcdir)\config\Make.rules.mak.js + +SLICE2JSFLAGS = $(SLICE2JSFLAGS) -I"$(slicedir)" diff --git a/js/demo/Ice/hello/README b/js/demo/Ice/hello/README new file mode 100644 index 00000000000..d49c149416b --- /dev/null +++ b/js/demo/Ice/hello/README @@ -0,0 +1,29 @@ +This demo illustrates how to invoke ordinary (twoway) operations, as +well as how to make oneway and batched invocations. + +To run the demo, first you need to start the Ice hello server. This +distribution includes server implementations in Python and C++, and +each one has its own README file with instructions for starting the +server. Please refer to the Python or C++ README in the appropriate +demo subdirectory for more information. + +Note: + + * To use the Python server you'll need a Python installation that is + compatible with the Ice for Python module included in Ice 3.5.1. + + * To use the C++ server you'll need a C++ compiler compatible with + the Ice 3.5.1 C++ distribution. + +After starting the server, open a separate window and start the +client: + +$ node Client.js + +To test timeouts you can use 'T' to set a timeout on the client proxy +and 'P' to set a delayed response in the server to cause a timeout. +You will notice that two "Hello World!" messages will be printed by +the server in this case. This is because the sayHello method is marked +as idempotent in the slice, meaning that Ice does not need to follow +the at-most-once retry semantics. See the manual for more information +about retry behavior. diff --git a/js/demo/Ice/hello/browser/Client.js b/js/demo/Ice/hello/browser/Client.js new file mode 100644 index 00000000000..23a720cca9e --- /dev/null +++ b/js/demo/Ice/hello/browser/Client.js @@ -0,0 +1,265 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice is licensed to you under the terms described in the +// ICE_LICENSE file included in this distribution. +// +// ********************************************************************** + +(function(){ + +var communicator = Ice.initialize(); + +var flushEnabled = false; +var batch = 0; + +// +// Create the hello proxy. +// +function createProxy() +{ + var hostname = document.location.hostname || "127.0.0.1"; + var proxy = communicator.stringToProxy("hello" + + ":ws -h " + hostname + " -p 8080 -r /demows" + + ":wss -h " + hostname + " -p 9090 -r /demowss"); + + // + // Set or clear the timeout. + // + var timeout = $("#timeout").val(); + proxy = proxy.ice_timeout(timeout > 0 ? timeout : -1); + + // + // Set the mode and protocol + // + var mode = $("#mode").val(); + if(mode == "twoway") + { + proxy = proxy.ice_twoway(); + } + else if(mode == "twoway-secure") + { + proxy = proxy.ice_twoway().ice_secure(true); + } + else if(mode == "oneway") + { + proxy = proxy.ice_oneway(); + } + else if(mode == "oneway-secure") + { + proxy = proxy.ice_oneway().ice_secure(true); + } + else if(mode == "oneway-batch") + { + proxy = proxy.ice_batchOneway(); + } + else if(mode == "oneway-batch-secure") + { + proxy = proxy.ice_batchOneway().ice_secure(true); + } + return Demo.HelloPrx.uncheckedCast(proxy); +} + +// +// Invoke sayHello. +// +function sayHello() +{ + setState(State.SendRequest); + + var proxy = createProxy(); + if(proxy.ice_isBatchOneway()) + { + batch++; + } + + return proxy.sayHello($("#delay").val()); +} + +// +// Flush batch requests. +// +function flush() +{ + batch = 0; + setState(State.FlushBatchRequests); + return communicator.flushBatchRequests(); +} + +// +// Shutdown the server. +// +function shutdown() +{ + setState(State.SendRequest); + + var proxy = createProxy(); + if(proxy.ice_isBatchOneway()) + { + batch++; + } + + return proxy.shutdown(); +} + +// +// Return an event handler suitable for "click" methods. The +// event handler calls the given function, handles exceptions +// and resets the state to Idle when the promise returned by +// the function is fulfilled. +// +var performEventHandler = function(fn) +{ + return function() + { + Ice.Promise.try( + function() + { + return fn.call(); + } + ).exception( + function(ex) + { + $("#output").val(ex.toString()); + } + ).finally( + function() + { + setState(State.Idle); + } + ); + return false; + } +} +var sayHelloClickHandler = performEventHandler(sayHello); +var shutdownClickHandler = performEventHandler(shutdown); +var flushClickHandler = performEventHandler(flush); + +// +// Handle the client state. +// +var State = { + Idle:0, + SendRequest:1, + FlushBatchRequests:2 +}; + +var state; + +function setState(newState, ex) +{ + function assert(v) + { + if(!v) + { + throw new Error("Assertion failed"); + } + } + + assert(state !== newState); + + switch(newState) + { + case State.Idle: + { + assert(state === undefined || state === State.SendRequest || state === State.FlushBatchRequests); + + // + // Hide the progress indicator. + // + $("#progress").hide(); + $("body").removeClass("waiting"); + + // + // Enable buttons. + // + $("#hello").removeClass("disabled").click(sayHelloClickHandler); + $("#shutdown").removeClass("disabled").click(shutdownClickHandler); + if(batch > 0) + { + $("#flush").removeClass("disabled").click(flushClickHandler); + } + break; + } + case State.SendRequest: + case State.FlushBatchRequests: + { + assert(state === State.Idle); + + // + // Reset the output. + // + $("#output").val(""); + + // + // Disable buttons. + // + $("#hello").addClass("disabled").off("click"); + $("#shutdown").addClass("disabled").off("click"); + $("#flush").addClass("disabled").off("click"); + + // + // Display the progress indicator and set the wait cursor. + // + $("#progress .message").text( + newState === State.SendRequest ? "Sending Request..." : "Flush Batch Requests..."); + $("#progress").show(); + $("body").addClass("waiting"); + break; + } + } + state = newState; +}; + +// +// Start in the idle state +// +setState(State.Idle); + +// +// Extract the url GET variables and put them in the _GET object. +// +var _GET = {}; +if(window.location.search.length > 1) +{ + window.location.search.substr(1).split("&").forEach( + function(pair) + { + pair = pair.split("="); + if(pair.length > 0) + { + _GET[decodeURIComponent(pair[0])] = pair.length > 1 ? decodeURIComponent(pair[1]) : ""; + } + }); +} + +// +// If the mode param is set, initialize the mode select box with that value. +// +if(_GET["mode"]) +{ + $("#mode").val(_GET["mode"]); +} + +// +// If the user selects a secure mode, ensure that the page is loaded over HTTPS +// so the web server SSL certificate is obtained. +// +$("#mode").on("change", + function(e) + { + var newMode = $(this).val(); + + if(document.location.protocol === "http:" && + (newMode === "twoway-secure" || newMode === "oneway-secure" || newMode === "oneway-batch-secure")) + { + var href = document.location.protocol + "//" + document.location.host + + document.location.pathname + "?mode=" + newMode; + href = href.replace("http", "https"); + href = href.replace("8080", "9090"); + document.location.assign(href); + } + }); + +}()); diff --git a/js/demo/Ice/hello/build.js b/js/demo/Ice/hello/build.js new file mode 100644 index 00000000000..3694185c575 --- /dev/null +++ b/js/demo/Ice/hello/build.js @@ -0,0 +1,10 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice is licensed to you under the terms described in the +// ICE_LICENSE file included in this distribution. +// +// ********************************************************************** + +var build = require ("../../../config/build").build(__dirname, ["Hello.ice"]); diff --git a/js/demo/Ice/hello/expect.py b/js/demo/Ice/hello/expect.py new file mode 100755 index 00000000000..85ce83f0fe3 --- /dev/null +++ b/js/demo/Ice/hello/expect.py @@ -0,0 +1,31 @@ +#!/usr/bin/env python +# ********************************************************************** +# +# Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +# +# This copy of Ice is licensed to you under the terms described in the +# ICE_LICENSE file included in this distribution. +# +# ********************************************************************** + +import sys, os + +path = [ ".", "..", "../..", "../../..", "../../../.." ] +head = os.path.dirname(sys.argv[0]) +if len(head) > 0: + path = [os.path.join(head, p) for p in path] +path = [os.path.abspath(p) for p in path if os.path.exists(os.path.join(p, "demoscript")) ] +if len(path) == 0: + raise RuntimeError("can't find toplevel directory!") +sys.path.append(path[0]) + +from demoscript import Util +from demoscript.Ice import hello + +server = Util.spawn('./server --Ice.PrintAdapterReady --Ice.Warn.Connections=0', Util.getMirrorDir("cpp"), mapping="cpp") +server.expect('.* ready') + +client = Util.spawn('node Client.js --Ice.Warn.Connections=0') +client.expect('.*==>') + +hello.run(client, server, False, False) diff --git a/js/demo/Ice/hello/index.html b/js/demo/Ice/hello/index.html new file mode 100644 index 00000000000..f4131b132cf --- /dev/null +++ b/js/demo/Ice/hello/index.html @@ -0,0 +1,195 @@ +<!doctype html> +<html class="no-js" lang="en"> + <head> + <meta charset="utf-8" /> + <meta name="viewport" content="width=device-width, initial-scale=1.0" /> + <title>Hello Demo | Ice for JavaScript</title> + <!-- Bundle with all the stylesheets used to build the user interface, + see config/Makefile in your distribution for details --> + <link rel="stylesheet" type="text/css" href="../../../assets/common.css" /> + <link rel="icon" type="image/x-icon" href="../../../assets/favicon.ico"> + </head> + <body> + <!-- Header section that contains title and navigation bar --> + <section id="header"> + <nav class="top-bar" data-topbar> + <ul class="title-area"> + <li class="name"> + <h1><a href="../../../index.html">Ice for JavaScript</a></h1> + </li> + <li class="toggle-topbar menu-icon"><a href="#">Menu</a></li> + </ul> + <section class="top-bar-section"> + <!-- Right Nav Section --> + <ul class="right"> + <li class="divider"></li> + <li><a href="#" id="viewReadme">Readme</a></li> + <li><a href="#" id="viewSource">Source</a></li> + </ul> + </section> + </nav> + <ul class="breadcrumbs"> + <li><a href="../../../index.html">Ice</a></li> + <li><a href="../../index.html">Demos</a></li> + <li class="current"><a href="#">Hello</a></li> + </ul> + </section> + + <!-- Main section that contains the user interface --> + <section role="main" id="body"> + <div class="row"> + <div class="large-12 medium-12 columns"> + <form> + <div class="row"> + <div class="small-3 columns"> + <label class="right inline" for="mode">Mode:</label> + </div> + <div class="small-9 columns"> + <select id="mode"> + <option value="twoway">Twoway</option> + <option value="twoway-secure">Twoway Secure</option> + <option value="oneway">Oneway</option> + <option value="oneway-secure">Oneway Secure</option> + <option value="oneway-batch">Oneway Batch</option> + <option value="oneway-batch-secure">Oneway Batch Secure</option> + </select> + </div> + </div> + <div class="row"> + <div class="small-3 columns"> + <label class="right inline">Timeout:</label> + </div> + <div class="small-9 columns"> + <div id="timeout" class="noUiSlider"></div> + </div> + </div> + <br/> + <div class="row"> + <div class="small-3 columns"> + <label class="right inline">Delay:</label> + </div> + <div class="small-9 columns"> + <div id="delay" class="noUiSlider"></div> + </div> + </div> + <div class="row"> + <div class="small-12 columns"> + <a href="#" class="button small" id="hello">Hello World!</a> + <a href="#" class="button small" id="shutdown">Shutdown</a> + <a href="#" class="button disabled small" id="flush">Flush</a> + </div> + </div> + <textarea id="output" class="disabled" readonly></textarea> + <div id="progress" class="row hide"> + <div class="small-12 columns left"> + <div class="inline left icon"></div> + <div class="text">Sending Request...</div> + </div> + </div> + </form> + </div> + </div> + </section> + + <!-- Modal dialog to show the client README --> + <div id="readme-modal" class="reveal-modal medium" data-reveal> + <div class="contents"> + <h4>Hello Demo Readme</h4> + <hr/> + <p>This demo illustrates how to invoke ordinary (twoway) operations, as + well as how to make oneway, secure, and batched invocations.</p> + + <p>To run the demo, first you need to start the Ice hello server. This + distribution includes server implementations in Python and C++, and + each one has its own README file with instructions for starting the + server. Please refer to the Python or C++ README in the appropriate + demo subdirectory for more information. + </p> + + <div class="panel callout radius"> + <ul> + <li>To use the Python server you'll need a Python installation that is + compatible with the Ice for Python module included in Ice 3.5.1.</li> + + <li>To use the C++ server you'll need a C++ compiler compatible with your + Ice for JavaScript distribution.</li> + </ul> + </div> + + <p>You can change the invocation mode using the <strong>"Mode"</strong> + select box; the default is "Twoway" invocation.</p> + + <p>To send an invocation, click the <strong>"Hello World!"</strong> button, + to shutdown the server click the <strong>"Shutdown"</strong> button, + and to flush batch requests click the <strong>"Flush"</strong> button + (this is only enabled when there are pending requests to flush).</p> + + <p>To test timeouts, you can use the timeout slider to set a timeout + on the client proxy and the delay slider to set a delayed response in + the server to cause a timeout.</p> + + <p>You will notice that two "Hello World!" messages will be printed by + the server in this case. This is because the <code>sayHello</code> method is marked + as idempotent in the Slice, meaning that Ice does not need to follow + the at-most-once retry semantics. See the + <a href="http://doc.zeroc.com/display/Ice/Automatic+Retries#AutomaticRetries-AutomaticRetriesforIdempotentOperations">manual</a> + for more information about retry behavior.</p> + </div> + <a class="close-reveal-modal">×</a> + </div> + <!-- Modal dialog to show the client source code --> + <div id="source-modal" class="reveal-modal" data-reveal> + <a class="close-reveal-modal">×</a> + <dl class="tabs" data-tab> + <dt></dt> + <dd class="active"><a href="#panel2-1">Slice</a></dd> + <dd><a href="#panel2-2">JavaScript</a></dd> + <dd><a href="#panel2-3">HTML</a></dd> + </dl> + <div class="tabs-content"> + <div class="content active" id="panel2-1"> + <h6>File: demo/Ice/hello/Hello.ice</h6> + <pre class="source language-c" data-code="Hello.ice"></pre> + </div> + <div class="content" id="panel2-2"> + <h6>File: demo/Ice/hello/browser/Client.js</h6> + <pre class="source" data-code="browser/Client.js"></pre> + </div> + <div class="content" id="panel2-3"> + <h6>File: demo/Ice/hello/index.html</h6> + <pre class="source" data-code="index.html"></pre> + </div> + </div> + </div> + <!-- Footer section --> + <section id="footer"> + <div class="logo"> + <h4><strong>ZeroC</strong></h4> + </div> + <div class="copyright"> + <h6>© 2014 ZeroC, Inc. All rights reserved.</h6> + </div> + </section> + <!-- Bundle with all the scripts used to build the user interface, + see assets/Makefile in your distribution for details --> + <script type="text/javascript" src="../../../assets/common.min.js"></script> + + <script type="text/javascript"> + + </script> + + <!-- Ice.js (Ice run-time library) --> + <script type="text/javascript" src="../../../lib/Ice.js"></script> + <!-- Hello.js (Demo generated code) --> + <script type="text/javascript" src="Hello.js"></script> + <!-- browser/Client.js (Hello Demo Application) --> + <script type="text/javascript" src="browser/Client.js"></script> + + <script type="text/javascript"> + if(["http:", "https:"].indexOf(document.location.protocol) !== -1) + { + checkGenerated(["Hello.js"]); + } + </script> + </body> +</html> diff --git a/js/demo/Ice/latency/.gitignore b/js/demo/Ice/latency/.gitignore new file mode 100644 index 00000000000..916894afcf6 --- /dev/null +++ b/js/demo/Ice/latency/.gitignore @@ -0,0 +1 @@ +Latency.js diff --git a/js/demo/Ice/latency/Client.js b/js/demo/Ice/latency/Client.js new file mode 100644 index 00000000000..b0a2034e40e --- /dev/null +++ b/js/demo/Ice/latency/Client.js @@ -0,0 +1,91 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice is licensed to you under the terms described in the +// ICE_LICENSE file included in this distribution. +// +// ********************************************************************** + +(function(){ + +require("Ice"); +require("./Latency"); + +var communicator; + +// +// Asynchronous loop, each call to the given function returns a +// promise that when fulfilled runs the next iteration. +// +function loop(fn, repetitions) +{ + var i = 0; + var next = function() + { + if(i++ < repetitions) + { + return fn.call().then(next); + } + }; + return next(); +} + +Ice.Promise.try( + function() + { + // + // Initialize the communicator and create a proxy to the + // ping object. + // + communicator = Ice.initialize(); + var repetitions = 10000; + var proxy = communicator.stringToProxy("ping:default -p 10000"); + + // + // Down-cast the proxy to the Demo.Ping interface. + // + return Demo.PingPrx.checkedCast(proxy).then( + function(obj) + { + console.log("pinging server " + repetitions + " times (this may take a while)"); + start = new Date().getTime(); + return loop( + function() + { + return obj.ice_ping(); + }, + repetitions + ).then( + function() + { + // + // Write the results. + // + total = new Date().getTime() - start; + console.log("time for " + repetitions + " pings: " + total + "ms"); + console.log("time per ping: " + (total / repetitions) + "ms"); + }); + }); + } +).finally( + function() + { + // + // Destroy the communicator if required. + // + if(communicator) + { + return communicator.destroy(); + } + } +).exception( + function(ex) + { + // + // Handle any exceptions above. + // + console.log(ex.toString()); + process.exit(1); + }); +}()); diff --git a/js/demo/Ice/latency/Latency.ice b/js/demo/Ice/latency/Latency.ice new file mode 100644 index 00000000000..2391b2667aa --- /dev/null +++ b/js/demo/Ice/latency/Latency.ice @@ -0,0 +1,19 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice is licensed to you under the terms described in the +// ICE_LICENSE file included in this distribution. +// +// ********************************************************************** + +#pragma once + +module Demo +{ + +class Ping +{ +}; + +}; diff --git a/js/demo/Ice/latency/Makefile b/js/demo/Ice/latency/Makefile new file mode 100644 index 00000000000..5b712f95b52 --- /dev/null +++ b/js/demo/Ice/latency/Makefile @@ -0,0 +1,16 @@ +# ********************************************************************** +# +# Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +# +# This copy of Ice is licensed to you under the terms described in the +# ICE_LICENSE file included in this distribution. +# +# ********************************************************************** + +top_srcdir = ../../.. + +TARGETS = Latency.js + +include $(top_srcdir)/config/Make.rules.js + +SLICE2JSFLAGS := $(SLICE2JSFLAGS) -I$(slicedir) diff --git a/js/demo/Ice/latency/Makefile.mak b/js/demo/Ice/latency/Makefile.mak new file mode 100644 index 00000000000..ded034bf05d --- /dev/null +++ b/js/demo/Ice/latency/Makefile.mak @@ -0,0 +1,16 @@ +# ********************************************************************** +# +# Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +# +# This copy of Ice is licensed to you under the terms described in the +# ICE_LICENSE file included in this distribution. +# +# ********************************************************************** + +top_srcdir = ..\..\.. + +TARGETS = Latency.js + +!include $(top_srcdir)\config\Make.rules.mak.js + +SLICE2JSFLAGS = $(SLICE2JSFLAGS) -I"$(slicedir)" diff --git a/js/demo/Ice/latency/README b/js/demo/Ice/latency/README new file mode 100644 index 00000000000..8f6f193a0b1 --- /dev/null +++ b/js/demo/Ice/latency/README @@ -0,0 +1,21 @@ +A simple latency test that measures the basic call dispatch delay of +Ice. + +To run the demo, first you need to start the Ice latency server. This +distribution includes server implementations in Python and C++, and +each one has its own README file with instructions for starting the +server. Please refer to the Python or C++ README in the appropriate +demo subdirectory for more information. + +Note: + + * To use the Python server you'll need a Python installation that is + compatible with the Ice for Python module included in Ice 3.5.1. + + * To use the C++ server you'll need a C++ compiler compatible with + the Ice 3.5.1 C++ distribution. + +After starting the server, open a separate window and start the +client: + +$ node Client.js diff --git a/js/demo/Ice/latency/browser/Client.js b/js/demo/Ice/latency/browser/Client.js new file mode 100644 index 00000000000..3a86f26c7ed --- /dev/null +++ b/js/demo/Ice/latency/browser/Client.js @@ -0,0 +1,161 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice is licensed to you under the terms described in the +// ICE_LICENSE file included in this distribution. +// +// ********************************************************************** + +(function(){ + +var Promise = Ice.Promise; + +// +// Initialize the communicator +// +var communicator = Ice.initialize(); + +// +// Run the latency test. +// +function run() +{ + // + // Create a proxy to the ping object. + // + var hostname = document.location.hostname || "127.0.0.1"; + var secure = document.location.protocol.indexOf("https") != -1; + var ref = secure ? + "ping:wss -h " + hostname + " -p 9090 -r /demowss" : + "ping:ws -h " + hostname + " -p 8080 -r /demows"; + var proxy = communicator.stringToProxy(ref); + + var repetitions = 1000; + + // + // Down-cast the proxy to the Demo.Ping interface. + // + return Demo.PingPrx.checkedCast(proxy).then( + function(obj) + { + writeLine("pinging server " + repetitions + " times (this may take a while)"); + start = new Date().getTime(); + return loop( + function() + { + return obj.ice_ping(); + }, + repetitions + ).then( + function() + { + // + // Write the results. + // + total = new Date().getTime() - start; + writeLine("time for " + repetitions + " pings: " + total + "ms"); + writeLine("time per ping: " + (total / repetitions) + "ms"); + setState(State.Idle); + }); + }); +} + +// +// Run button event handler. +// +$("#run").click( + function() + { + // + // Run the latency loop if not already running. + // + if(state !== State.Running) + { + setState(State.Running); + + Ice.Promise.try( + function() + { + return run(); + } + ).exception( + function(ex) + { + $("#output").val(ex.toString()); + } + ).finally( + function() + { + setState(State.Idle); + } + ); + } + return false; + }); + +// +// Asynchronous loop: each call to the given function returns a +// promise that when fulfilled runs the next iteration. +// +function loop(fn, repetitions) +{ + var i = 0; + var next = function() + { + if(i++ < repetitions) + { + return fn.call().then(next); + } + }; + return next(); +} + +// +// Helper function to write the output. +// +function writeLine(msg) +{ + $("#output").val($("#output").val() + msg + "\n"); + $("#output").scrollTop($("#output").get(0).scrollHeight); +} + +// +// Handle the client state. +// +var State = { + Idle:0, + Running: 1 +}; + +var state; + +function setState(s, ex) +{ + if(s != state) + { + switch(s) + { + case State.Running: + { + $("#output").val(""); + $("#run").addClass("disabled"); + $("#progress").show(); + $("body").addClass("waiting"); + break; + } + case State.Idle: + { + $("#run").removeClass("disabled"); + $("#progress").hide(); + $("body").removeClass("waiting"); + break; + } + } + state = s; + } +} + +setState(State.Idle); + +}()); diff --git a/js/demo/Ice/latency/build.js b/js/demo/Ice/latency/build.js new file mode 100644 index 00000000000..4ef18bb7834 --- /dev/null +++ b/js/demo/Ice/latency/build.js @@ -0,0 +1,10 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice is licensed to you under the terms described in the +// ICE_LICENSE file included in this distribution. +// +// ********************************************************************** + +require ("../../../config/build").build(__dirname, ["Latency.ice"]); diff --git a/js/demo/Ice/latency/expect.py b/js/demo/Ice/latency/expect.py new file mode 100755 index 00000000000..3e0c8d19d2f --- /dev/null +++ b/js/demo/Ice/latency/expect.py @@ -0,0 +1,36 @@ +#!/usr/bin/env python +# ********************************************************************** +# +# Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +# +# This copy of Ice is licensed to you under the terms described in the +# ICE_LICENSE file included in this distribution. +# +# ********************************************************************** + +import sys, os, signal + +path = [ ".", "..", "../..", "../../..", "../../../.." ] +head = os.path.dirname(sys.argv[0]) +if len(head) > 0: + path = [os.path.join(head, p) for p in path] +path = [os.path.abspath(p) for p in path if os.path.exists(os.path.join(p, "demoscript")) ] +if len(path) == 0: + raise RuntimeError("can't find toplevel directory!") +sys.path.append(path[0]) + +from demoscript import Util + +server = Util.spawn('./server --Ice.PrintAdapterReady', Util.getMirrorDir("cpp"), mapping="cpp") +server.expect('.* ready') + +sys.stdout.write("testing ping... ") +sys.stdout.flush() +client = Util.spawn('node Client.js') +client.waitTestSuccess(timeout=100) +print("ok") + +server.kill(signal.SIGINT) +server.waitTestSuccess() + +print(client.before) diff --git a/js/demo/Ice/latency/index.html b/js/demo/Ice/latency/index.html new file mode 100644 index 00000000000..7d5fba1c27b --- /dev/null +++ b/js/demo/Ice/latency/index.html @@ -0,0 +1,139 @@ +<!doctype html> +<html class="no-js" lang="en"> + <head> + <meta charset="utf-8" /> + <meta name="viewport" content="width=device-width, initial-scale=1.0" /> + <title>Latency Demo | Ice for JavaScript</title> + <!-- Bundle with all the stylesheets used to build the user interface, + see assets/Makefile in your distribution for details --> + <link rel="stylesheet" type="text/css" href="../../../assets/common.css" /> + <link rel="icon" type="image/x-icon" href="../../../assets/favicon.ico"> + </head> + <body> + <!-- Header section that contains title and navigation bar --> + <section id="header"> + <nav class="top-bar" data-topbar> + <ul class="title-area"> + <li class="name"> + <h1><a href="../../../index.html">Ice for JavaScript</a></h1> + </li> + <li class="toggle-topbar menu-icon"><a href="#">Menu</a></li> + </ul> + <section class="top-bar-section"> + <!-- Right Nav Section --> + <ul class="right"> + <li class="divider"></li> + <li><a href="#" id="viewReadme">Readme</a></li> + <li><a href="#" id="viewSource">Source</a></li> + </ul> + </section> + </nav> + <ul class="breadcrumbs"> + <li><a href="../../../index.html">Ice</a></li> + <li><a href="../../index.html">Demos</a></li> + <li class="current"><a href="#">Latency</a></li> + </ul> + </section> + <!-- Main section that contains the user interface --> + <section role="main" id="body"> + <div class="row"> + <div class="large-12 medium-12 columns"> + <form> + <a href="#" class="button small" id="run">Run</a> + <div class="row"> + <div class="small-12 columns"> + <textarea id="output" class="disabled" readonly></textarea> + </div> + </div> + <div id="progress" class="row hide"> + <div class="small-12 columns left"> + <div class="inline left icon"></div> + <div class="text">Running...</div> + </div> + </div> + </form> + </div> + </div> + </section> + <!-- Modal dialog to show the client README --> + <div id="readme-modal" class="reveal-modal medium" data-reveal> + <h4>Latency Demo Readme</h4> + <hr/> + <p>A simple latency test that measures the basic call dispatch delay of + Ice.</p> + + <p>To run the demo, first you need to start the Ice latency server. This + distribution includes server implementations in Python and C++, and + each one has its own README file with instructions for starting the + server. Please refer to the Python or C++ README in the appropriate + demo subdirectory for more information. + </p> + + <div class="panel callout radius"> + <ul> + <li>To use the Python server you'll need a Python installation that is + compatible with the Ice for Python module included in Ice 3.5.1.</li> + + <li>To use the C++ server you'll need a C++ compiler compatible with your + Ice for JavaScript distribution.</li> + </ul> + </div> + + <p>Then you can use the <strong>"Run"</strong> button to run this client.</p> + + <div class="panel callout radius"> + <p>The client is configured to use WSS secure endpoints when the page + is loaded over HTTPS and WS unsecure endpoints when loaded over HTTP.</p> + </div> + <a class="close-reveal-modal">×</a> + </div> + <!-- Modal dialog to show the client source code --> + <div id="source-modal" class="reveal-modal" data-reveal> + <a class="close-reveal-modal">×</a> + <dl class="tabs" data-tab> + <dt></dt> + <dd class="active"><a href="#panel2-1">Slice</a></dd> + <dd><a href="#panel2-2">JavaScript</a></dd> + <dd><a href="#panel2-3">HTML</a></dd> + </dl> + <div class="tabs-content"> + <div class="content active" id="panel2-1"> + <h6>File: Ice/latency/Latency.ice</h6> + <pre class="source language-c" data-code="Latency.ice"></pre> + </div> + <div class="content" id="panel2-2"> + <h6>File: Ice/latency/browser/Client.js</h6> + <pre class="source" data-code="browser/Client.js"></pre> + </div> + <div class="content" id="panel2-3"> + <h6>File: Ice/latency/index.html</h6> + <pre class="source" data-code="index.html"></pre> + </div> + </div> + </div> + <!-- Footer section --> + <section id="footer"> + <div class="logo"> + <h4><strong>ZeroC</strong></h4> + </div> + <div class="copyright"> + <h6>© 2014 ZeroC, Inc. All rights reserved.</h6> + </div> + </section> + <!-- Bundle with all the scripts used to build the user interface, + see assets/Makefile in your distribution for details --> + <script type="text/javascript" src="../../../assets/common.min.js"></script> + <!-- Ice.js (Ice run-time library) --> + <script type="text/javascript" src="../../../lib/Ice.js"></script> + <!-- Latency.js (Demo generated code) --> + <script type="text/javascript" src="Latency.js"></script> + <!-- browser/Client.js (Latency Demo Application) --> + <script type="text/javascript" src="browser/Client.js"></script> + <script type="text/javascript"> + if(["http:", "https:"].indexOf(document.location.protocol) !== -1) + { + checkGenerated(["Latency.js"]); + } + </script> + </body> +</html> diff --git a/js/demo/Ice/minimal/.gitignore b/js/demo/Ice/minimal/.gitignore new file mode 100644 index 00000000000..2cfc557c40f --- /dev/null +++ b/js/demo/Ice/minimal/.gitignore @@ -0,0 +1,3 @@ +Hello.js +Client.min.js +Client.min.js.gz diff --git a/js/demo/Ice/minimal/Client.js b/js/demo/Ice/minimal/Client.js new file mode 100644 index 00000000000..c357df0922b --- /dev/null +++ b/js/demo/Ice/minimal/Client.js @@ -0,0 +1,58 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice is licensed to you under the terms described in the +// ICE_LICENSE file included in this distribution. +// +// ********************************************************************** + +(function(){ + +require("Ice"); +require("./Hello"); + +var communicator; + +Ice.Promise.try( + function() + { + // + // Initialize the communicator and create a proxy to the hello object. + // + communicator = Ice.initialize(); + var proxy = communicator.stringToProxy("hello:tcp -h localhost -p 10000"); + + // + // Down-cast the proxy to the hello object interface. + // + return Demo.HelloPrx.checkedCast(proxy).then( + function(hello) + { + // + // Invoke the sayHello method. + // + return hello.sayHello(); + }); + } +).finally( + function() + { + // + // Destroy the communicator if required. + // + if(communicator) + { + return communicator.destroy(); + } + } +).exception( + function(ex) + { + // + // Handle any exceptions above. + // + console.log(ex.toString()); + process.exit(1); + }); +}()); diff --git a/js/demo/Ice/minimal/Hello.ice b/js/demo/Ice/minimal/Hello.ice new file mode 100644 index 00000000000..8e596e50d9a --- /dev/null +++ b/js/demo/Ice/minimal/Hello.ice @@ -0,0 +1,20 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice is licensed to you under the terms described in the +// ICE_LICENSE file included in this distribution. +// +// ********************************************************************** + +#pragma once + +module Demo +{ + +interface Hello +{ + void sayHello(); +}; + +}; diff --git a/js/demo/Ice/minimal/Makefile b/js/demo/Ice/minimal/Makefile new file mode 100644 index 00000000000..8cadc2de833 --- /dev/null +++ b/js/demo/Ice/minimal/Makefile @@ -0,0 +1,30 @@ +# ********************************************************************** +# +# Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +# +# This copy of Ice is licensed to you under the terms described in the +# ICE_LICENSE file included in this distribution. +# +# ********************************************************************** + +top_srcdir = ../../.. + +TARGETS = Hello.js + +ifeq ($(OPTIMIZE),yes) +TARGETS := $(TARGETS) browser/Client.min.js browser/Client.min.js.gz +endif + +include $(top_srcdir)/config/Make.rules.js + +SLICE2JSFLAGS := $(SLICE2JSFLAGS) -I$(slicedir) + +ifeq ($(OPTIMIZE),yes) + +CLOSUREFLAGS := $(CLOSUREFLAGS) --warning_level QUIET + +browser/Client.min.js browser/Client.min.js.gz: Hello.js browser/Client.js $(libdir)/Ice.min.js + @rm -f browser/Client.min.js browser/Client.min.js.gz + java -jar $(CLOSURE_PATH)/compiler.jar $(CLOSUREFLAGS) --js $(libdir)/Ice.min.js Hello.js browser/Client.js --js_output_file browser/Client.min.js + gzip -c9 browser/Client.min.js > browser/Client.min.js.gz +endif diff --git a/js/demo/Ice/minimal/Makefile.mak b/js/demo/Ice/minimal/Makefile.mak new file mode 100644 index 00000000000..4a4074dca1f --- /dev/null +++ b/js/demo/Ice/minimal/Makefile.mak @@ -0,0 +1,41 @@ +# ********************************************************************** +# +# Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +# +# This copy of Ice is licensed to you under the terms described in the +# ICE_LICENSE file included in this distribution. +# +# ********************************************************************** + +top_srcdir = ..\..\.. + +TARGETS = Hello.js + +!if "$(OPTIMIZE)" == "yes" +TARGETS = $(TARGETS) browser\Client.min.js + +!if "$(GZIP_PATH)" != "" +TARGETS = $(TARGETS) browser\Client.min.js.gz +!endif + +!endif + +!include $(top_srcdir)\config\Make.rules.mak.js + +SLICE2JSFLAGS = $(SLICE2JSFLAGS) -I"$(slicedir)" +!if "$(OPTIMIZE)" == "yes" + +CLOSUREFLAGS = $(CLOSUREFLAGS) --warning_level QUIET + +browser\Client.min.js: browser\Client.js Hello.js $(libdir)\Ice.min.js + @del /q browser\Client.min.js + java -jar $(CLOSURE_PATH)\compiler.jar $(CLOSUREFLAGS) --js $(libdir)\Ice.js Hello.js \ + browser\Client.js --js_output_file browser\Client.min.js + +!if "$(GZIP_PATH)" != "" +browser\Client.min.js.gz: browser\Client.min.js + @del /q Client.min.js.gz + "$(GZIP_PATH)" -c9 browser\Client.min.js > browser\Client.min.js.gz +!endif + +!endif diff --git a/js/demo/Ice/minimal/README b/js/demo/Ice/minimal/README new file mode 100644 index 00000000000..69236a2ba45 --- /dev/null +++ b/js/demo/Ice/minimal/README @@ -0,0 +1,25 @@ +This demo is a minimal Ice "hello world" application. Each time the +client is run a "sayHello" invocation is sent to the server. + +To run the demo, first you need to start the Ice minimal server. This +distribution includes server implementations in Python and C++, and +each one has its own README file with instructions for starting the +server. Please refer to the Python or C++ README in the appropriate +demo subdirectory for more information. + +Note: + + * To use the Python server you'll need a Python installation that is + compatible with the Ice for Python module included in Ice 3.5.1. + + * To use the C++ server you'll need a C++ compiler compatible with + the Ice 3.5.1 C++ distribution. + +After starting the server, open a separate window and start the +client: + +$ node Client.js + +Note that this demo hardwires port 10000. If port 10000 is not +available on your machine, you need to edit both client and server +to use a free port. diff --git a/js/demo/Ice/minimal/browser/Client.js b/js/demo/Ice/minimal/browser/Client.js new file mode 100644 index 00000000000..5bb07b816d8 --- /dev/null +++ b/js/demo/Ice/minimal/browser/Client.js @@ -0,0 +1,127 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice is licensed to you under the terms described in the +// ICE_LICENSE file included in this distribution. +// +// ********************************************************************** + +(function(){ + +// +// Initialize the communicator. +// +var communicator = Ice.initialize(); + +function sayHello() +{ + Ice.Promise.try( + function() + { + setState(State.Busy); + + // + // Create a proxy for the hello object + // + var hostname = document.location.hostname || "127.0.0.1"; + var proxy = communicator.stringToProxy("hello:ws -h " + hostname + " -p 10000"); + + // + // Down-cast this proxy to the derived interface Demo::Hello + // using checkedCast, and invoke the sayHello operation if + // the checkedCast succeeds. + // + return Demo.HelloPrx.checkedCast(proxy).then( + function(hello) + { + return hello.sayHello(); + }); + } + ).exception( + function(ex) + { + // + // Handle any exceptions thrown above. + // + $("#output").val(ex.toString()); + } + ).finally( + function() + { + setState(State.Idle); + } + ); + return false; +} + +// +// Handle the client state +// +var State = { + Idle: 0, + Busy: 1 +}; + +var state; + +function setState(newState) +{ + function assert(v) + { + if(!v) + { + throw new Error("Assertion failed"); + } + } + + assert(state !== newState); + switch(newState) + { + case State.Idle: + { + assert(state === undefined || state == State.Busy); + + // + // Hide the progress indicator. + // + $("#progress").hide(); + $("body").removeClass("waiting"); + + // + // Enable buttons + // + $("#hello").removeClass("disabled").click(sayHello); + break; + } + case State.Busy: + { + assert(state == State.Idle); + + // + // Clear any previous error messages. + // + $("#output").val(""); + + // + // Disable buttons. + // + $("#hello").addClass("disabled").off("click"); + + // + // Display the progress indicator and set the wait cursor. + // + $("#progress").show(); + $("body").addClass("waiting"); + break; + } + } + state = newState; +} + +// +// Start in the idle state +// +setState(State.Idle); + +}()); diff --git a/js/demo/Ice/minimal/build.js b/js/demo/Ice/minimal/build.js new file mode 100644 index 00000000000..90af1d5df57 --- /dev/null +++ b/js/demo/Ice/minimal/build.js @@ -0,0 +1,10 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice is licensed to you under the terms described in the +// ICE_LICENSE file included in this distribution. +// +// ********************************************************************** + +require ("../../../config/build").build(__dirname, ["Hello.ice"]); diff --git a/js/demo/Ice/minimal/expect.py b/js/demo/Ice/minimal/expect.py new file mode 100755 index 00000000000..896d0c80a7b --- /dev/null +++ b/js/demo/Ice/minimal/expect.py @@ -0,0 +1,35 @@ +#!/usr/bin/env python +# ********************************************************************** +# +# Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +# +# This copy of Ice is licensed to you under the terms described in the +# ICE_LICENSE file included in this distribution. +# +# ********************************************************************** + +import sys, os, signal + +path = [ ".", "..", "../..", "../../..", "../../../.." ] +head = os.path.dirname(sys.argv[0]) +if len(head) > 0: + path = [os.path.join(head, p) for p in path] +path = [os.path.abspath(p) for p in path if os.path.exists(os.path.join(p, "demoscript")) ] +if len(path) == 0: + raise RuntimeError("can't find toplevel directory!") +sys.path.append(path[0]) + +from demoscript import Util + +server = Util.spawn('./server --Ice.PrintAdapterReady', Util.getMirrorDir("cpp"), mapping="cpp") +server.expect('.* ready') + +sys.stdout.write("testing... ") +sys.stdout.flush() +client = Util.spawn('node Client.js') +client.waitTestSuccess() +server.expect('Hello World!') +print("ok") + +server.kill(signal.SIGINT) +server.waitTestFail() diff --git a/js/demo/Ice/minimal/index.html b/js/demo/Ice/minimal/index.html new file mode 100644 index 00000000000..8931515672d --- /dev/null +++ b/js/demo/Ice/minimal/index.html @@ -0,0 +1,205 @@ +<!doctype html> +<html class="no-js" lang="en"> + <head> + <meta charset="utf-8" /> + <meta name="viewport" content="width=device-width, initial-scale=1.0" /> + <title>Minimal Demo | Ice for JavaScript</title> + <!-- Bundle with all the stylesheets used to build the user interface, + see assets/Makefile in your distribution for details --> + <link rel="stylesheet" type="text/css" href="../../../assets/common.css" /> + <link rel="icon" type="image/x-icon" href="../../../assets/favicon.ico"> + </head> + <body> + <!-- Header section that contains title and navigation bar --> + <section id="header"> + <nav class="top-bar" data-topbar> + <ul class="title-area"> + <li class="name"> + <h1><a href="../../../index.html">Ice for JavaScript</a></h1> + </li> + <li class="toggle-topbar menu-icon"><a href="#">Menu</a></li> + </ul> + <section class="top-bar-section"> + <!-- Right Nav Section --> + <ul class="right"> + <li class="divider"></li> + <li><a href="#" id="viewReadme">Readme</a></li> + <li><a href="#" id="viewSource">Source</a></li> + </ul> + </section> + </nav> + <ul class="breadcrumbs"> + <li><a href="../../../index.html">Ice</a></li> + <li><a href="../../index.html">Demos</a></li> + <li class="current"><a href="#">Minimal</a></li> + </ul> + </section> + <!-- Main section that contains the user interface --> + <section role="main" id="body"> + <div class="row"> + <div class="large-12 medium-12 columns"> + <form> + <div class="row"> + <div class="small-12 columns"> + <a href="#" class="button small" id="hello">Hello World!</a> + </div> + </div> + <div class="row"> + <div class="small-12 columns"> + <textarea id="output" readonly></textarea> + </div> + </div> + <div id="progress" class="row hide"> + <div class="small-12 columns left"> + <div class="inline left icon"></div> + <div class="text">Sending Request...</div> + </div> + </div> + </form> + </div> + </div> + </section> + <!-- Modal dialog to show the client README --> + <div id="readme-modal" class="reveal-modal" data-reveal> + <h4>Minimal Demo Readme</h4> + <hr/> + <p>This demo is a minimal Ice "hello world" application. Each time the + client is run a "sayHello" invocation is sent to the server.</p> + + <p>To run the demo, first you need to start the Ice minimal server. This + distribution includes server implementations in Python and C++, and + each one has its own README file with instructions for starting the + server. Please refer to the Python or C++ README in the appropriate + demo subdirectory for more information. + </p> + + <div class="panel callout radius"> + <ul> + <li>To use the Python server you'll need a Python installation that is + compatible with the Ice for Python module included in Ice 3.5.1.</li> + + <li>To use the C++ server you'll need a C++ compiler compatible with your + Ice for JavaScript distribution.</li> + </ul> + </div> + + <p>To run the client click the <strong>"Hello World!"</strong> button.</p> + <div class="panel callout radius"> + <p>Note that this demo hardwires port 10000. If port 10000 is not + available on your machine, you need to edit both client and server + to use a free port.</p> + </div> + <h4>Using the minified scripts</h4> + <p>When the demo is built with optimizations enabled it creates a minified + script <code>browser/Client.min.js</code> that includes: + </p> + <ul> + <li>Ice.js (The Ice run-time library)</li> + <li>Hello.js (The generated code for this demo)</li> + <li>browser/Client.js (The demo source)</li> + </ul> + <p>To use the minified version you should edit the <code>demo/Ice/minimal/index.html</code> + file and comment out the non-optimized scripts:</p> + <pre> + <!-- Scripts used during development, for optimized builds + comment out the following scripts and use browser/Client.min.js below --> + <!-- Ice.js (Ice run-time library) --> + <script type="text/javascript" src="../../../lib/Ice.js"></script> + <!-- Hello.js (Demo generated code) --> + <script type="text/javascript" src="Hello.js"></script> + <!-- browser/Client.js (Minimal Demo Application) --> + <script type="text/javascript" src="browser/Client.js"></script> + </pre> + <p>Then uncomment the script tag for the minified version</p> + <pre> + <!-- Uncomment the following line to use a minified version of the + scripts that includes: the Ice run-time library, the generated code + and the demo application. --> + <!--<script type="text/javascript" src="browser/Client.min.js"></script>--> + </pre> + <a class="close-reveal-modal">×</a> + </div> + <!-- Modal dialog to show the client source code --> + <div id="source-modal" class="reveal-modal" data-reveal> + <a class="close-reveal-modal">×</a> + <dl class="tabs" data-tab> + <dt></dt> + <dd class="active"><a href="#panel2-1">Slice</a></dd> + <dd><a href="#panel2-2">JavaScript</a></dd> + <dd><a href="#panel2-3">HTML</a></dd> + </dl> + <div class="tabs-content"> + <div class="content active" id="panel2-1"> + <h6>File: Ice/minimal/Hello.ice</h6> + <pre class="source language-c" data-code="Hello.ice"></pre> + </div> + <div class="content" id="panel2-2"> + <h6>File: Ice/minimal/browser/Client.js</h6> + <pre class="source" data-code="browser/Client.js"></pre> + </div> + <div class="content" id="panel2-3"> + <h6>File: Ice/minimal/index.html</h6> + <pre class="source" data-code="index.html"></pre> + </div> + </div> + </div> + <div id="no-https-modal" class="reveal-modal" data-reveal> + <p>This client uses a non-secure WebSocket connection, but your browser does not allow + the client to make a non-secure connection from a page loaded via HTTPS. You can run the + demo from an HTTP page by navigating to <a href=""></a>. + </p> + </div> + <!-- Footer section --> + <section id="footer"> + <div class="logo"> + <h4><strong>ZeroC</strong></h4> + </div> + <div class="copyright"> + <h6>© 2014 ZeroC, Inc. All rights reserved.</h6> + </div> + </section> + <!-- Bundle with all the scripts used to build the user interface, + see assets/Makefile in your distribution for details --> + <script type="text/javascript" src="../../../assets/common.min.js"></script> + <!-- Scripts used during development, for optimized builds + comment the following scripts and uncomment browser/Client.min.js + below --> + <!-- Ice.js (Ice run-time library) --> + <script type="text/javascript" src="../../../lib/Ice.js"></script> + <!-- Hello.js (Demo generated code) --> + <script type="text/javascript" src="Hello.js"></script> + <!-- browser/Client.js (Minimal Demo Application) --> + <script type="text/javascript" src="browser/Client.js"></script> + <!-- Uncomment the following line to use a minified version of the + scripts that includes: (the Ice run-time library, the generated code + and the demo application). --> + <!--<script type="text/javascript" src="browser/Client.min.js"></script>--> + <script type="text/javascript"> + // + // Firefox and IE we doesn't allow WS connections from + // HTTPS pages. + // + if(document.location.protocol === "https:" && + (navigator.userAgent.indexOf("MSIE") !== -1 || + navigator.userAgent.indexOf("Firefox") !== -1 || + navigator.userAgent.indexOf("Trident/7.0") !== -1)) + { + var href = "http://" + document.location.hostname + ":8080" + document.location.pathname; + $("#no-https-modal a").attr("href", href); + $("#no-https-modal a").text(href); + $("#no-https-modal").foundation({ + reveal: + { + close_on_background_click: false, + close_on_esc: false + } + }); + $("#no-https-modal").foundation("reveal", "open"); + } + else if(document.location.protocol == "http:") + { + checkGenerated(["Hello.js"]); + } + </script> + </body> +</html> diff --git a/js/demo/Ice/throughput/.gitignore b/js/demo/Ice/throughput/.gitignore new file mode 100644 index 00000000000..6e8a0fb4232 --- /dev/null +++ b/js/demo/Ice/throughput/.gitignore @@ -0,0 +1 @@ +Throughput.js diff --git a/js/demo/Ice/throughput/Client.js b/js/demo/Ice/throughput/Client.js new file mode 100644 index 00000000000..20d0bd1ddf4 --- /dev/null +++ b/js/demo/Ice/throughput/Client.js @@ -0,0 +1,397 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice is licensed to you under the terms described in the +// ICE_LICENSE file included in this distribution. +// +// ********************************************************************** + +(function(){ + +require("Ice"); +require("./Throughput"); + +function menu() +{ + process.stdout.write( + "usage:\n" + + "\n" + + "toggle type of data to send:\n" + + "1: sequence of bytes (default)\n" + + "2: sequence of strings (\"hello\")\n" + + "3: sequence of structs with a string (\"hello\") and a double\n" + + "4: sequence of structs with two ints and a double\n" + + "\n" + + "select test to run:\n" + + "t: Send sequence as twoway\n" + + "o: Send sequence as oneway\n" + + "r: Receive sequence\n" + + "e: Echo (send and receive) sequence\n" + + "\n" + + "other commands:\n" + + "s: shutdown server\n" + + "x: exit\n" + + "?: help\n" + + "\n"); +}; + +// +// Asynchronous loop, each call to the given function returns a +// promise that when fulfilled runs the next iteration. +// +function loop(fn, repetitions) +{ + var i = 0; + var next = function() + { + if(i++ < repetitions) + { + return fn.call().then(next); + } + }; + return next(); +} + +// +// Initialize sequences. +// +var byteSeq = new Buffer(Demo.ByteSeqSize); +for(var i = 0; i < Demo.ByteSeqSize; ++i) +{ + byteSeq[i] = 0; +} + +var stringSeq = []; +for(var i = 0; i < Demo.StringSeqSize; ++i) +{ + stringSeq[i] = "hello"; +} + +var structSeq = []; +for(var i = 0; i < Demo.StringDoubleSeqSize; ++i) +{ + structSeq[i] = new Demo.StringDouble(); + structSeq[i].s = "hello"; + structSeq[i].d = 3.14; +} + +var fixedSeq = []; +for(var i = 0; i < Demo.FixedSeqSize; ++i) +{ + fixedSeq[i] = new Demo.Fixed(); + fixedSeq[i].i = 0; + fixedSeq[i].j = 0; + fixedSeq[i].d = 0; +} + +var communicator; +Ice.Promise.try( + function() + { + var currentType = "1"; + var repetitions = 100; + + var seqSize = Demo.ByteSeqSize; + var seq = byteSeq; + var wireSize = 1; + + // + // Initialize the communicator and create a proxy + // to the throughput object. + // + communicator = Ice.initialize(); + var proxy = communicator.stringToProxy("throughput:default -p 10000"); + + // + // Down-cast the proxy to the Demo.Throughput interface. + // + return Demo.ThroughputPrx.checkedCast(proxy).then( + function(twoway) + { + var oneway = twoway.ice_oneway(); + menu(); + process.stdout.write("==> "); + var keyLoop = new Ice.Promise(); + + function processKey(key) + { + if(key == "x") + { + keyLoop.succeed(); + return; + } + + var proxy; + var operation; + + if(key == "1" || key == "2" || key == "3" || key == "4") + { + currentType = key; + + // + // Select the sequence data type to use by this test. + // + switch(currentType) + { + case "1": + { + console.log("using byte sequences"); + seqSize = Demo.ByteSeqSize; + seq = byteSeq; + wireSize = 1; + break; + } + + case "2": + { + console.log("using string sequences"); + seqSize = Demo.StringSeqSize; + seq = stringSeq; + wireSize = seq[0].length; + break; + } + + case "3": + { + console.log("using variable-length struct sequences"); + seqSize = Demo.StringDoubleSeqSize; + seq = structSeq; + wireSize = seq[0].s.length; + wireSize += 8; // Size of double on the wire. + break; + } + + case "4": + { + console.log("using fixed-length struct sequences"); + seqSize = Demo.FixedSeqSize; + seq = fixedSeq; + wireSize = 16; // Size of two ints and a double on the wire. + break; + } + } + } + else if(key == "t" || key == "o" || key == "r" || key == "e") + { + // + // Select the proxy and operation to use by this test. + // + switch(key) + { + case "t": + case "o": + { + proxy = key == "o" ? oneway : twoway; + if(currentType == 1) + { + operation = proxy.sendByteSeq; + } + else if(currentType == 2) + { + operation = proxy.sendStringSeq; + } + else if(currentType == 3) + { + operation = proxy.sendStructSeq; + } + else if(currentType == 4) + { + operation = proxy.sendFixedSeq; + } + process.stdout.write("sending"); + break; + } + + case "r": + { + proxy = twoway; + if(currentType == 1) + { + operation = proxy.recvByteSeq; + } + else if(currentType == 2) + { + operation = proxy.recvStringSeq; + } + else if(currentType == 3) + { + operation = proxy.recvStructSeq; + } + else if(currentType == 4) + { + operation = proxy.recvFixedSeq; + } + process.stdout.write("receiving"); + break; + } + + case "e": + { + proxy = twoway; + if(currentType == 1) + { + operation = proxy.echoByteSeq; + } + else if(currentType == 2) + { + operation = proxy.echoStringSeq; + } + else if(currentType == 3) + { + operation = proxy.echoStructSeq; + } + else if(currentType == 4) + { + operation = proxy.echoFixedSeq; + } + process.stdout.write("sending and receiving"); + break; + } + } + + process.stdout.write(" " + repetitions); + switch(currentType) + { + case "1": + { + process.stdout.write(" byte"); + break; + } + case "2": + { + process.stdout.write(" string"); + break; + } + case "3": + { + process.stdout.write(" variable-length struct"); + break; + } + + case "4": + { + process.stdout.write(" fixed-length struct"); + break; + } + } + + process.stdout.write(" sequences of size " + seqSize); + + if(key == "o") + { + process.stdout.write(" as oneway"); + } + console.log("..."); + + var start = new Date().getTime(); + var args = key != "r" ? [seq] : []; + return loop( + function() + { + return operation.apply(proxy, args); + }, + repetitions + ).then( + function() + { + // + // Write the results. + // + var total = new Date().getTime() - start; + console.log("time for " + repetitions + " sequences: " + total + " ms"); + console.log("time per sequence: " + total / repetitions + " ms"); + + var mbit = repetitions * seqSize * wireSize * 8.0 / total / 1000.0; + if(key == "e") + { + mbit *= 2; + } + mbit = Math.round(mbit * 100) / 100; + console.log("throughput: " + mbit + " Mbps"); + }); + } + else if(key == "s") + { + return twoway.shutdown(); + process.stdout.write("==> "); + } + else if(key == "?") + { + process.stdout.write("\n"); + menu(); + } + else + { + console.log("unknown command `" + key + "'"); + process.stdout.write("\n"); + menu(); + } + } + + // + // Process keys sequentially. We chain the promise objects + // returned by processKey(). Once we have process all the + // keys we print the prompt and resume the standard input. + // + process.stdin.resume(); + var promise = new Ice.Promise().succeed(); + process.stdin.on("data", + function(buffer) + { + process.stdin.pause(); + var data = buffer.toString("utf-8").trim().split(""); + // Process each key + data.forEach(function(key) + { + promise = promise.then( + function(r) + { + return processKey(key); + } + ).exception( + function(ex) + { + console.log(ex.toString()); + }); + }); + // Once we're done, print the prompt + promise.then(function() + { + if(!keyLoop.completed()) + { + process.stdout.write("==> "); + process.stdin.resume(); + } + }); + data = []; + }); + + return keyLoop; + }); + } +).finally( + function() + { + // + // Destroy the communicator if required. + // + if(communicator) + { + return communicator.destroy(); + } + } +).then( + function() + { + process.exit(0); + }, + function(ex) + { + // + // Handle any exceptions above. + // + console.log(ex.toString()); + process.exit(1); + }); +}()); diff --git a/js/demo/Ice/throughput/Makefile b/js/demo/Ice/throughput/Makefile new file mode 100644 index 00000000000..36cfcf309d4 --- /dev/null +++ b/js/demo/Ice/throughput/Makefile @@ -0,0 +1,16 @@ +# ********************************************************************** +# +# Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +# +# This copy of Ice is licensed to you under the terms described in the +# ICE_LICENSE file included in this distribution. +# +# ********************************************************************** + +top_srcdir = ../../.. + +TARGETS = Throughput.js + +include $(top_srcdir)/config/Make.rules.js + +SLICE2JSFLAGS := $(SLICE2JSFLAGS) -I$(slicedir) diff --git a/js/demo/Ice/throughput/Makefile.mak b/js/demo/Ice/throughput/Makefile.mak new file mode 100644 index 00000000000..47703ca9848 --- /dev/null +++ b/js/demo/Ice/throughput/Makefile.mak @@ -0,0 +1,16 @@ +# ********************************************************************** +# +# Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +# +# This copy of Ice is licensed to you under the terms described in the +# ICE_LICENSE file included in this distribution. +# +# ********************************************************************** + +top_srcdir = ..\..\.. + +TARGETS = Throughput.js + +!include $(top_srcdir)\config\Make.rules.mak.js + +SLICE2JSFLAGS = $(SLICE2JSFLAGS) -I"$(slicedir)" diff --git a/js/demo/Ice/throughput/README b/js/demo/Ice/throughput/README new file mode 100644 index 00000000000..c16a0436934 --- /dev/null +++ b/js/demo/Ice/throughput/README @@ -0,0 +1,26 @@ +A simple throughput demo that allows you to send sequences of various +types between client and server and to measure the maximum bandwidth +that can be achieved using serialized synchronous requests. + +To run the demo, first you need to start the Ice throughput server. +This distribution includes server implementations in Python and C++, +and each one has its own README file with instructions for starting +the server. Please refer to the Python or C++ README in the +appropriate demo subdirectory for more information. + +Note: + + * To use the Python server you'll need a Python installation that is + compatible with the Ice for Python module included in Ice 3.5.1. + + * To use the C++ server you'll need a C++ compiler compatible with + the Ice 3.5.1 C++ distribution. + +After starting the server, open a separate window and start the +client: + +$ node Client.js + +The performance for byte sequences is expected to be greater than +for other types because the cost of marshaling and unmarshaling is +lower than for more complex types. diff --git a/js/demo/Ice/throughput/Throughput.ice b/js/demo/Ice/throughput/Throughput.ice new file mode 100644 index 00000000000..c2216a15bfc --- /dev/null +++ b/js/demo/Ice/throughput/Throughput.ice @@ -0,0 +1,63 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice is licensed to you under the terms described in the +// ICE_LICENSE file included in this distribution. +// +// ********************************************************************** + +#pragma once + +module Demo +{ + +sequence<byte> ByteSeq; +const int ByteSeqSize = 500000; + +sequence<string> StringSeq; +const int StringSeqSize = 50000; + +struct StringDouble +{ + string s; + double d; +}; +sequence<StringDouble> StringDoubleSeq; +const int StringDoubleSeqSize = 50000; + +struct Fixed +{ + int i; + int j; + double d; +}; +sequence<Fixed> FixedSeq; +const int FixedSeqSize = 50000; + +interface Throughput +{ + bool needsWarmup(); + void startWarmup(); + void endWarmup(); + + void sendByteSeq(ByteSeq seq); + ByteSeq recvByteSeq(); + ByteSeq echoByteSeq(ByteSeq seq); + + void sendStringSeq(StringSeq seq); + StringSeq recvStringSeq(); + StringSeq echoStringSeq(StringSeq seq); + + void sendStructSeq(StringDoubleSeq seq); + StringDoubleSeq recvStructSeq(); + StringDoubleSeq echoStructSeq(StringDoubleSeq seq); + + void sendFixedSeq(FixedSeq seq); + FixedSeq recvFixedSeq(); + FixedSeq echoFixedSeq(FixedSeq seq); + + void shutdown(); +}; + +}; diff --git a/js/demo/Ice/throughput/browser/Client.js b/js/demo/Ice/throughput/browser/Client.js new file mode 100644 index 00000000000..133481e3ea4 --- /dev/null +++ b/js/demo/Ice/throughput/browser/Client.js @@ -0,0 +1,345 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice is licensed to you under the terms described in the +// ICE_LICENSE file included in this distribution. +// +// ********************************************************************** + +(function(){ + +var ThroughputPrx = Demo.ThroughputPrx; + +// +// Initialize sequences. +// +var byteSeq = new ArrayBuffer(); +for(var i = 0; i < Demo.ByteSeqSize; ++i) +{ + byteSeq[i] = 0; +} + +var stringSeq = []; +for(var i = 0; i < Demo.StringSeqSize; ++i) +{ + stringSeq[i] = "hello"; +} + +var structSeq = []; +for(var i = 0; i < Demo.StringDoubleSeqSize; ++i) +{ + structSeq[i] = new Demo.StringDouble(); + structSeq[i].s = "hello"; + structSeq[i].d = 3.14; +} + +var fixedSeq = []; +for(var i = 0; i < Demo.FixedSeqSize; ++i) +{ + fixedSeq[i] = new Demo.Fixed(); + fixedSeq[i].i = 0; + fixedSeq[i].j = 0; + fixedSeq[i].d = 0; +} + +var communicator = Ice.initialize(); + +// +// Run the throughput test. +// +function run() +{ + // + // Create a proxy to the throughput object. + // + var hostname = document.location.hostname || "127.0.0.1"; + var secure = document.location.protocol.indexOf("https") != -1; + var ref = secure ? + "throughput:wss -h " + hostname + " -p 9090 -r /demowss" : + "throughput:ws -h " + hostname + " -p 8080 -r /demows"; + var proxy = communicator.stringToProxy(ref); + + // + // Down-cast the proxy to the Demo.Throughput interface. + // + return ThroughputPrx.checkedCast(proxy).then( + function(twoway) + { + oneway = twoway.ice_oneway(); + + var seq; + var seqSize + var wireSize; + var proxy; + var operation; + var repetitions = 100; + + var data = $("#data").val(); + // + // Get the sequence data + // + if(data == "byte-seq") + { + seq = byteSeq; + seqSize = Demo.ByteSeqSize; + seq = byteSeq; + wireSize = 1; + } + else if(data == "string-seq") + { + seq = stringSeq; + seqSize = Demo.StringSeqSize; + seq = stringSeq; + wireSize = seq[0].length; + } + else if(data == "struct-seq") + { + seq = structSeq; + seqSize = Demo.StringDoubleSeqSize; + seq = structSeq; + wireSize = seq[0].s.length; + // + // Size of double on the wire. + // + wireSize += 8; + } + else if(data == "fixed-seq") + { + seq = fixedSeq; + seqSize = Demo.FixedSeqSize; + seq = fixedSeq; + // + // Size of two ints and a double on the wire. + // + wireSize = 16; + } + + // + // Get the proxy and operation + // + var test = $("#test").val(); + if(test == "twoway" || test == "oneway") + { + proxy = test == "twoway" ? twoway : oneway; + if(data == "byte-seq") + { + operation = proxy.sendByteSeq; + } + else if(data == "string-seq") + { + operation = proxy.sendStringSeq; + } + else if(data == "struct-seq") + { + operation = proxy.sendStructSeq; + } + else if(data == "fixed-seq") + { + operation = proxy.sendFixedSeq; + } + write("sending"); + } + else if(test == "receive") + { + proxy = twoway; + if(data == "byte-seq") + { + operation = proxy.recvByteSeq; + } + else if(data == "string-seq") + { + operation = proxy.recvStringSeq; + } + else if(data == "struct-seq") + { + operation = proxy.recvStructSeq; + } + else if(data == "fixed-seq") + { + operation = proxy.recvFixedSeq; + } + write("receiving"); + } + else if(test == "echo") + { + proxy = twoway; + if(data == "byte-seq") + { + operation = proxy.echoByteSeq; + } + else if(data == "string-seq") + { + operation = proxy.echoStringSeq; + } + else if(data == "struct-seq") + { + operation = proxy.echoStructSeq; + } + else if(data == "fixed-seq") + { + operation = proxy.echoFixedSeq; + } + write("sending and receiving"); + } + + write(" " + repetitions); + if(data == "byte-seq") + { + write(" byte"); + } + else if(data == "string-seq") + { + write(" string"); + } + else if(data == "struct-seq") + { + write(" variable-length struct"); + } + else if(data == "fixed-seq") + { + write(" fixed-length struct"); + } + write(" sequences of size " + seqSize); + if(test == "oneway") + { + write(" as oneway"); + } + writeLine("..."); + + // + // Invoke the test operation in a loop with the required + // arguments. + // + // We chain the promises. A test operation is called only + // once the promise for the previous operation is + // fulfilled. + // + var start = new Date().getTime(); + var args = test != "receive" ? [seq] : []; + return loop( + function() + { + return operation.apply(proxy, args); + }, + repetitions + ).then( + function() + { + // + // Write the results. + // + var total = new Date().getTime() - start; + writeLine("time for " + repetitions + " sequences: " + total + " ms"); + writeLine("time per sequence: " + total / repetitions + " ms"); + + var mbit = repetitions * seqSize * wireSize * 8.0 / total / 1000.0; + if(test == "echo") + { + mbit *= 2; + } + mbit = Math.round(mbit * 100) / 100; + writeLine("throughput: " + mbit + " Mbps"); + }); + }); +} + +$("#run").click( + function() + { + // + // Run the throughput loop if not already running. + // + if(state !== State.Running) + { + setState(State.Running); + + Ice.Promise.try( + function() + { + return run(); + } + ).exception( + function(ex) + { + $("#output").val(ex.toString()); + } + ).finally( + function() + { + setState(State.Idle); + } + ); + } + return false; + }); + +// +// Asynchronous loop: each call to the given function returns a +// promise that when fulfilled runs the next iteration. +// +function loop(fn, repetitions) +{ + var i = 0; + var next = function() + { + if(i++ < repetitions) + { + return fn.call().then(next); + } + }; + return next(); +} + +// +// Helper functions to write the output. +// +function write(msg) +{ + $("#output").val($("#output").val() + msg); +} + +function writeLine(msg) +{ + write(msg + "\n"); + $("#output").scrollTop($("#output").get(0).scrollHeight); +} + +// +// Handle the client state. +// +var State = { + Idle:0, + Running: 1 +}; +var state; + +function setState(s, ex) +{ + if(s != state) + { + switch(s) + { + case State.Running: + { + $("#output").val(""); + $("#run").addClass("disabled"); + $("#progress").show(); + $("body").addClass("waiting"); + break; + } + case State.Idle: + { + $("#run").removeClass("disabled"); + $("#progress").hide(); + $("body").removeClass("waiting"); + break; + } + } + state = s; + } +} + +setState(State.Idle); + +}()); diff --git a/js/demo/Ice/throughput/build.js b/js/demo/Ice/throughput/build.js new file mode 100644 index 00000000000..160797dafcf --- /dev/null +++ b/js/demo/Ice/throughput/build.js @@ -0,0 +1,10 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice is licensed to you under the terms described in the +// ICE_LICENSE file included in this distribution. +// +// ********************************************************************** + +require ("../../../config/build").build(__dirname, ["Throughput.ice"]); diff --git a/js/demo/Ice/throughput/expect.py b/js/demo/Ice/throughput/expect.py new file mode 100755 index 00000000000..c134c708034 --- /dev/null +++ b/js/demo/Ice/throughput/expect.py @@ -0,0 +1,30 @@ +#!/usr/bin/env python +# ********************************************************************** +# +# Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +# +# This copy of Ice is licensed to you under the terms described in the +# ICE_LICENSE file included in this distribution. +# +# ********************************************************************** + +import sys, os + +path = [ ".", "..", "../..", "../../..", "../../../.." ] +head = os.path.dirname(sys.argv[0]) +if len(head) > 0: + path = [os.path.join(head, p) for p in path] +path = [os.path.abspath(p) for p in path if os.path.exists(os.path.join(p, "demoscript")) ] +if len(path) == 0: + raise RuntimeError("can't find toplevel directory!") +sys.path.append(path[0]) + +from demoscript import Util +from demoscript.Ice import throughput + +server = Util.spawn('./server --Ice.PrintAdapterReady', Util.getMirrorDir("cpp"), mapping="cpp") +server.expect('.* ready') + +client = Util.spawn('node Client.js') + +throughput.run(client, server) diff --git a/js/demo/Ice/throughput/index.html b/js/demo/Ice/throughput/index.html new file mode 100644 index 00000000000..890c900c1f9 --- /dev/null +++ b/js/demo/Ice/throughput/index.html @@ -0,0 +1,181 @@ +<!doctype html> +<html class="no-js" lang="en"> + <head> + <meta charset="utf-8" /> + <meta name="viewport" content="width=device-width, initial-scale=1.0" /> + <title>Throughput Demo | Ice for JavaScript</title> + <!-- Bundle with all the stylesheets used to build the user interface, + see assets/Makefile in your distribution for details --> + <link rel="stylesheet" type="text/css" href="../../../assets/common.css" /> + <link rel="icon" type="image/x-icon" href="../../../assets/favicon.ico"> + </head> + <body> + <!-- Header section that contains title and navigation bar --> + <section id="header"> + <nav class="top-bar" data-topbar> + <ul class="title-area"> + <li class="name"> + <h1><a href="../../../index.html">Ice for JavaScript</a></h1> + </li> + <li class="toggle-topbar menu-icon"><a href="#">Menu</a></li> + </ul> + <section class="top-bar-section"> + <!-- Right Nav Section --> + <ul class="right"> + <li class="divider"></li> + <li><a href="#" id="viewReadme">Readme</a></li> + <li><a href="#" id="viewSource">Source</a></li> + </ul> + </section> + </nav> + <ul class="breadcrumbs"> + <li><a href="../../../index.html">Ice</a></li> + <li><a href="../../index.html">Demos</a></li> + <li class="current"><a href="#">Throughput</a></li> + </ul> + </section> + <!-- Main section that contains the user interface --> + <section role="main" id="body"> + <div class="row"> + <div class="large-12 medium-12 columns"> + <form> + <div class="row"> + <div class="small-3 columns"> + <label class="right inline" for="data">Data:</label> + </div> + <div class="small-9 columns"> + <select id="data"> + <option value="byte-seq">sequence of bytes (default)</option> + <option value="string-seq">sequence of strings ("hello")</option> + <option value="struct-seq">sequence of structs with a string ("hello") and a double</option> + <option value="fixed-seq">sequence of structs with two ints and a double</option> + </select> + </div> + </div> + <div class="row"> + <div class="small-3 columns"> + <label class="right inline" for="test">Test:</label> + </div> + <div class="small-9 columns"> + <select id="test"> + <option value="twoway">Send sequence as twoway</option> + <option value="oneway">Send sequence as oneway</option> + <option value="receive">Receive sequence</option> + <option value="echo">Echo (send and receive) sequence</option> + </select> + </div> + </div> + <div class="row"> + <div class="small-12 columns"> + <a href="#" class="button small" id="run">Run</a> + </div> + </div> + <div class="row"> + <div class="small-12 columns"> + <textarea id="output" class="disabled" readonly></textarea> + </div> + </div> + <div id="progress" class="row hide"> + <div class="small-12 columns left"> + <div class="inline left icon"></div> + <div class="text">Running...</div> + </div> + </div> + </form> + </div> + </div> + </section> + <!-- Modal dialog to show the client README --> + <div id="readme-modal" class="reveal-modal medium" data-reveal> + <h4>Throughput Demo Readme</h4> + <hr/> + <p>A simple throughput demo that allows you to send sequences of various + types between client and server and to measure the maximum bandwidth + that can be achieved using serialized synchronous requests.</p> + + <p>To run the demo, first you need to start the Ice throughput server. This + distribution includes server implementations in Python and C++, and + each one has its own README file with instructions for starting the + server. Please refer to the Python or C++ README in the appropriate + demo subdirectory for more information. + </p> + + <div class="panel callout radius"> + <ul> + <li>To use the Python server you'll need a Python installation that is + compatible with the Ice for Python module included in Ice 3.5.1.</li> + + <li>To use the C++ server you'll need a C++ compiler compatible with your + Ice for JavaScript distribution.</li> + </ul> + </div> + + <p>You can change the data type using the <strong>"Data"</strong> select + box. The <strong>"Test"</strong> select box allows you to select which test + to run.</p> + + <p>Then you can use the <strong>"Run"</strong> button to run this client.</p> + + <div class="panel callout radius"> + <p>The performance for byte sequences is expected to be greater than + for other types because the cost of marshaling and unmarshaling is + lower than for more complex types.</p> + </div> + + <div class="panel callout radius"> + <p>The client is configured to use WSS secure endpoints when the page + is loaded over HTTPS and WS unsecure endpoints when loaded over HTTP.</p> + </div> + <a class="close-reveal-modal">×</a> + </div> + <!-- Modal dialog to show the client source code --> + <div id="source-modal" class="reveal-modal" data-reveal> + <a class="close-reveal-modal">×</a> + <dl class="tabs" data-tab> + <dt></dt> + <dd class="active"><a href="#panel2-1">Slice</a></dd> + <dd><a href="#panel2-2">JavaScript</a></dd> + <dd><a href="#panel2-3">HTML</a></dd> + </dl> + <div class="tabs-content"> + <div class="content active" id="panel2-1"> + <h6>File: Ice/throughput/Throughput.ice</h6> + <pre class="source language-c" data-code="Throughput.ice"></pre> + </div> + <div class="content" id="panel2-2"> + <h6>File: Ice/throughput/browser/Client.js</h6> + <pre class="source" data-code="browser/Client.js"></pre> + </div> + <div class="content" id="panel2-3"> + <h6>File: Ice/throughput/index.html</h6> + <pre class="source" data-code="index.html"></pre> + </div> + </div> + </div> + <!-- Footer section --> + <section id="footer"> + <div class="logo"> + <h4><strong>ZeroC</strong></h4> + </div> + <div class="copyright"> + <h6>© 2014 ZeroC, Inc. All rights reserved.</h6> + </div> + </section> + <!-- Bundle with all the scripts used to build the user interface, + see assets/Makefile in your distribution for details --> + <script type="text/javascript" src="../../../assets/common.min.js"></script> + <!-- Ice.js (Ice run-time library) --> + <script type="text/javascript" src="../../../lib/Ice.js"></script> + <!-- Throughput.js (Demo generated code) --> + <script type="text/javascript" src="Throughput.js"></script> + <!-- browser/Client.js (Throughput Demo Application) --> + <script type="text/javascript" src="browser/Client.js"></script> + + <script type="text/javascript"> + if(["http:", "https:"].indexOf(document.location.protocol) !== -1) + { + checkGenerated(["Throughput.js"]); + } + </script> + </body> +</html> diff --git a/js/demo/Makefile b/js/demo/Makefile new file mode 100644 index 00000000000..c0766fc9342 --- /dev/null +++ b/js/demo/Makefile @@ -0,0 +1,22 @@ +# ********************************************************************** +# +# Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +# +# This copy of Ice is licensed to you under the terms described in the +# ICE_LICENSE file included in this distribution. +# +# ********************************************************************** + +top_srcdir = .. + +include $(top_srcdir)/config/Make.rules.js + +SUBDIRS = Ice Glacier2 ChatDemo + +$(EVERYTHING):: + @for subdir in $(SUBDIRS); \ + do \ + echo "making $@ in $$subdir"; \ + ( cd $$subdir && $(MAKE) $@ ) || exit 1; \ + done + diff --git a/js/demo/Makefile.mak b/js/demo/Makefile.mak new file mode 100644 index 00000000000..a872a477ce8 --- /dev/null +++ b/js/demo/Makefile.mak @@ -0,0 +1,19 @@ +# ********************************************************************** +# +# Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +# +# This copy of Ice is licensed to you under the terms described in the +# ICE_LICENSE file included in this distribution. +# +# ********************************************************************** + +top_srcdir = .. + +!include $(top_srcdir)\config\Make.rules.mak.js + +SUBDIRS = Ice Glacier2 ChatDemo + +$(EVERYTHING):: + @for %i in ( $(SUBDIRS) ) do \ + @echo "making $@ in %i" && \ + cmd /c "cd %i && $(MAKE) -nologo -f Makefile.mak $@" || exit 1 diff --git a/js/demo/README b/js/demo/README new file mode 100644 index 00000000000..02f8fa38099 --- /dev/null +++ b/js/demo/README @@ -0,0 +1,7 @@ +This directory contains demos for various Ice components. The demos +are provided to get you started on how to use a particular feature or +coding technique. See the README file in each subdirectory for details +on the demos. + +For more examples of the features of the Ice services (Glacier2, IceGrid, +IceStorm) please see the demos in the Ice for C++ distibution. diff --git a/js/demo/build.js b/js/demo/build.js new file mode 100644 index 00000000000..ccccb400efa --- /dev/null +++ b/js/demo/build.js @@ -0,0 +1,10 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice is licensed to you under the terms described in the +// ICE_LICENSE file included in this distribution. +// +// ********************************************************************** + +require("../config/build.js").buildDirectory(__dirname);
\ No newline at end of file diff --git a/js/demo/index.html b/js/demo/index.html new file mode 100644 index 00000000000..f43267b9fe4 --- /dev/null +++ b/js/demo/index.html @@ -0,0 +1,97 @@ +<!doctype html> +<html class="no-js" lang="en"> + <head> + <meta charset="utf-8" /> + <meta name="viewport" content="width=device-width, initial-scale=1.0" /> + <title>Demos | Ice for JavaScript</title> + <link rel="stylesheet" type="text/css" href="../assets/common.css" /> + <link rel="icon" type="image/x-icon" href="../assets/favicon.ico"> + </head> + <body> + <div id="header"> + <nav class="top-bar" data-topbar> + <ul class="title-area"> + <li class="name"> + <h1><a href="../index.html">Ice for JavaScript</a></h1> + </li> + </ul> + </nav> + <ul class="breadcrumbs"> + <li><a href="../index.html">Ice</a></li> + <li class="current"><a href="#">Demos</a></li> + </ul> + </div> + <section role="main" id="body"> + <div class="row"> + <div class="large-12 medium-12 columns"> + <ul class="small-block-grid-1 medium-block-grid-2 large-block-grid-3"> + <li> + <ul class="pricing-table"> + <li class="title">Hello</li> + <li class="description">This demo illustrates how to invoke ordinary (twoway) operations, as + well as how to invoke oneway operations, secure + invocations, and how to use batched invocations.</li> + <li class="cta-button"><a class="button expand" href="Ice/hello/index.html">GO</a></li> + </ul> + </li> + <li> + <ul class="pricing-table"> + <li class="title">Minimal</li> + <li class="description">This demo illustrates a minimal Ice application.</li> + <li class="cta-button"><a class="button expand" href="Ice/minimal/index.html">GO</a></li> + </ul> + </li> + <li> + <ul class="pricing-table"> + <li class="title">Bidir</li> + <li class="description">This demo shows how to use bidirectional connections for callbacks.</li> + <li class="cta-button"><a class="button expand" href="Ice/bidir/index.html">GO</a></li> + </ul> + </li> + + <li> + <ul class="pricing-table"> + <li class="title">Latency</li> + <li class="description">A simple latency test that measures the basic call dispatch delay of Ice.</li> + <li class="cta-button"><a class="button expand" href="Ice/latency/index.html">GO</a></li> + </ul> + </li> + <li> + <ul class="pricing-table"> + <li class="title">Throughput</li> + <li class="description">A simple throughput demo that allows you to send sequences of + various types between client and server and to measure the maximum + bandwidth that can be achieved.</li> + <li class="cta-button"><a class="button expand" href="Ice/throughput/index.html">GO</a></li> + </ul> + </li> + <li> + <ul class="pricing-table"> + <li class="title">Chat</li> + <li class="description">A very simple chat client that illustrates the Glacier2 session API.</li> + <li class="cta-button"><a class="button expand" href="Glacier2/chat/index.html">GO</a></li> + </ul> + </li> + <li> + <ul class="pricing-table"> + <li class="title">Chat Demo</li> + <li class="description">An Ice for JavaScript client for ZeroC's + <a href="http://www.zeroc.com/chat/index.html">Chat Demo</a>.</li> + <li class="cta-button"><a class="button expand" href="ChatDemo/index.html">GO</a></li> + </ul> + </li> + </ul> + </div> + </div> + </section> + <div id="footer"> + <div class="logo"> + <h4><strong>ZeroC</strong></h4> + </div> + <div class="copyright"> + <h6>© 2014 ZeroC, Inc. All rights reserved.</h6> + </div> + </div> + <script type="text/javascript" src="../assets/common.min.js"></script> + </body> +</html> |