/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
 * You can obtain one at http://mozilla.org/MPL/2.0/. */

/**
 * MozTCPSocket exposes a TCP client and server sockets
 * to highly privileged apps. It provides a buffered, non-blocking
 * interface for sending. For receiving, it uses an asynchronous,
 * event handler based interface.
 */

#include "domstubs.idl"
#include "nsIDOMEvent.idl"
#include "nsITCPSocketChild.idl"
#include "nsIDOMTCPServerSocket.idl"

interface nsISocketTransport;

// Bug 731746 - Allow chrome JS object to implement nsIDOMEventTarget
// nsITCPSocket should be an nsIEventTarget but js objects
// cannot be an nsIEventTarget yet
// #include "nsIEventTarget.idl"

// Bug 723206 - Constructors implemented in JS from IDL should be
//              allowed to have arguments
//
//  Once bug 723206 will be fixed, this method could be replaced by
//  arguments when instantiating a TCPSocket object. For example it will
//  be possible to do (similarly to the WebSocket API):
//    var s = new MozTCPSocket(host, port);

// Bug 797561 - Expose a server tcp socket API to web applications


[scriptable, uuid(65f6d2c8-4be6-4695-958d-0735e8935289)]
interface nsIDOMTCPSocket : nsISupports
{
  /**
   * Create and return a socket object which will attempt to connect to
   * the given host and port.
   *
   * @param host The hostname of the server to connect to.
   * @param port The port to connect to.
   * @param options An object specifying one or more parameters which
   *                determine the details of the socket.
   *
   *        useSecureTransport: true to create an SSL socket. Defaults to false.
   *
   *        binaryType: "arraybuffer" to use ArrayBuffer
   *          instances in the ondata callback and as the argument
   *          to send. Defaults to "string", to use JavaScript strings.
   *
   * @return The new TCPSocket instance.
   */
  nsIDOMTCPSocket open(in DOMString host, in unsigned short port, [optional] in jsval options);

  /**
   * Listen on a port
   *
   * @param localPort The port of the server socket. Pass -1 to indicate no preference,
   *                  and a port will be selected automatically.
   * @param options An object specifying one or more parameters which
   *                determine the details of the socket.
   *
   *        binaryType: "arraybuffer" to use ArrayBuffer
   *          instances in the ondata callback and as the argument
   *          to send. Defaults to "string", to use JavaScript strings.
   * @param backlog The maximum length the queue of pending connections may grow to.
   *                This parameter may be silently limited by the operating system.
   *                Pass -1 to use the default value.
   *
   * @return The new TCPServerSocket instance.
   */
  nsIDOMTCPServerSocket listen(in unsigned short localPort, [optional] in jsval options,
                               [optional] in unsigned short backlog);

  /**
   * Enable secure on channel.
   */
  void upgradeToSecure();

  /**
   * The host of this socket object.
   */
  readonly attribute DOMString host;

  /**
   * The port of this socket object.
   */
  readonly attribute unsigned short port;

  /**
   * True if this socket object is an SSL socket.
   */
  readonly attribute boolean ssl;

  /**
   * The number of bytes which have previously been buffered by calls to
   * send on this socket.
   */
  readonly attribute unsigned long bufferedAmount;

  /**
   * Pause reading incoming data and invocations of the ondata handler until
   * resume is called.
   */
  void suspend();

  /**
   * Resume reading incoming data and invoking ondata as usual.
   */
  void resume();

  /**
   * Close the socket.
   */
  void close();

  /**
   * Write data to the socket.
   *
   * @param data The data to write to the socket. If
   *             binaryType: "arraybuffer" was passed in the options
   *             object, then this object should be an ArrayBuffer instance.
   *             If binaryType: "string" was passed, or if no binaryType
   *             option was specified, then this object should be an
   *             ordinary JavaScript string.
   * @param byteOffset The offset within the data from which to begin writing.
   *                   Has no effect on non-ArrayBuffer data.
   * @param byteLength The number of bytes to write. Has no effect on
   *                   non-ArrayBuffer data.
   *
   * @return Send returns true or false as a hint to the caller that
   *         they may either continue sending more data immediately, or
   *         may want to wait until the other side has read some of the
   *         data which has already been written to the socket before
   *         buffering more. If send returns true, then less than 64k
   *         has been buffered and it's safe to immediately write more.
   *         If send returns false, then more than 64k has been buffered,
   *         and the caller may wish to wait until the ondrain event
   *         handler has been called before buffering more data by more
   *         calls to send.
   */
  boolean send(in jsval data, [optional] in unsigned long byteOffset, [optional] in unsigned long byteLength);

  /**
   * The readyState attribute indicates which state the socket is currently
   * in. The state will be either "connecting", "open", "closing", or "closed".
   */
  readonly attribute DOMString readyState;

  /**
   * The binaryType attribute indicates which mode this socket uses for
   * sending and receiving data. If the binaryType: "arraybuffer" option
   * was passed to the open method that created this socket, binaryType
   * will be "arraybuffer". Otherwise, it will be "string".
   */
  readonly attribute DOMString binaryType;

  /**
   * The onopen event handler is called when the connection to the server
   * has been established. If the connection is refused, onerror will be
   * called, instead.
   */
  attribute jsval onopen;

  /**
   * After send has buffered more than 64k of data, it returns false to
   * indicate that the client should pause before sending more data, to
   * avoid accumulating large buffers. This is only advisory, and the client
   * is free to ignore it and buffer as much data as desired, but if reducing
   * the size of buffers is important (especially for a streaming application)
   * ondrain will be called once the previously-buffered data has been written
   * to the network, at which point the client can resume calling send again.
   */
  attribute jsval ondrain;

  /**
   * The ondata handler will be called repeatedly and asynchronously after
   * onopen has been called, every time some data was available from the server
   * and was read. If binaryType: "arraybuffer" was passed to open, the data
   * attribute of the event object will be an ArrayBuffer. If not, it will be a
   * normal JavaScript string.
   *
   * At any time, the client may choose to pause reading and receiving ondata
   * callbacks, by calling the socket's suspend() method. Further invocations
   * of ondata will be paused until resume() is called.
   */
  attribute jsval ondata;

  /**
   * The onerror handler will be called when there is an error. The data
   * attribute of the event passed to the onerror handler will have a
   * description of the kind of error.
   *
   * If onerror is called before onopen, the error was connection refused,
   * and onclose will not be called. If onerror is called after onopen,
   * the connection was lost, and onclose will be called after onerror.
   */
  attribute jsval onerror;

  /**
   * The onclose handler is called once the underlying network socket
   * has been closed, either by the server, or by the client calling
   * close.
   *
   * If onerror was not called before onclose, then either side cleanly
   * closed the connection.
   */
  attribute jsval onclose;
};

/*
 * This interface is implemented in TCPSocket.js as an internal interfaces
 * for use in cross-process socket implementation.
 * Needed to account for multiple possible types that can be provided to
 * the socket callbacks as arguments.
 */
[scriptable, uuid(b1235064-9a08-4714-ad03-1212e4562803)]
interface nsITCPSocketInternal : nsISupports {
  // Trigger the callback for |type| and provide a DOMError() object with the given data
  void callListenerError(in DOMString type, in DOMString name);

  // Trigger the callback for |type| and provide a string argument
  void callListenerData(in DOMString type, in DOMString data);

  // Trigger the callback for |type| and provide an ArrayBuffer argument
  void callListenerArrayBuffer(in DOMString type, in jsval data);

  // Trigger the callback for |type| with no argument
  void callListenerVoid(in DOMString type);

  // Update the DOM object's readyState.
  // @param readyState
  //        new ready state to be set to TCPSocket.
  void updateReadyState(in DOMString readyState);

  // Update the DOM object's bufferedAmount value with a tracking number to
  // ensure the update request is sent after child's send() invocation.
  // @param bufferedAmount
  //        TCPSocket parent's bufferedAmount.
  // @param trackingNumber
  //        A number to ensure the bufferedAmount is updated after data
  //        from child are sent to parent.
  void updateBufferedAmount(in uint32_t bufferedAmount,
                            in uint32_t trackingNumber);

  // Create a socket object on the parent side.
  // This is called in accepting any open request on the parent side.
  // 
  // @param transport
  //        The accepted socket transport.
  // @param binaryType
  //        "arraybuffer" to use ArrayBuffer instances 
  //        in the ondata callback and as the argument to send.
  // @param window
  //        An object to create ArrayBuffer for this window. See Bug 831107.
  nsIDOMTCPSocket createAcceptedParent(in nsISocketTransport transport,
                                       in DOMString binaryType,
                                       in nsIDOMWindow window);

  // Create a DOM socket on the child side
  // This is called when the socket is accepted on the parent side.
  //
  // @param socketChild
  //        The socket child object for the IPC implementation.
  // @param binaryType
  //        "arraybuffer" to use ArrayBuffer instances
  //        in the ondata callback and as the argument to send.
  // @param window
  //        An object to create ArrayBuffer for this window. See Bug 831107.
  nsIDOMTCPSocket createAcceptedChild(in nsITCPSocketChild socketChild,
                                      in DOMString binaryType,
                                      in nsIDOMWindow window);

  // Set App ID.
  void setAppId(in unsigned long appId);

  // Set a callback that handles the request from a TCP socket parent when that
  // socket parent wants to notify that its bufferedAmount is updated.
  void setOnUpdateBufferedAmountHandler(in jsval handler);

  // Providing child process with ability to pass more arguments to parent's
  // send() function.
  // @param trackingNumber
  //        To ensure the request to update bufferedAmount in child is after
  //        lastest send() invocation from child.
  void onRecvSendFromChild(in jsval data, in unsigned long byteOffset,
                           in unsigned long byteLength, in unsigned long trackingNumber);
};

/**
 * nsITCPSocketEvent is the event object which is passed as the
 * first argument to all the event handler callbacks. It contains
 * the socket that was associated with the event, the type of event,
 * and the data associated with the event (if any).
 */

[scriptable, uuid(0f2abcca-b483-4539-a3e8-345707f75c44)]
interface nsITCPSocketEvent : nsISupports {
  /**
   * The socket object which produced this event.
   */
  readonly attribute nsIDOMTCPSocket target;

  /**
   * The type of this event. One of:
   *
   * open
   * error
   * data
   * drain
   * close
   */
  readonly attribute DOMString type;

  /**
   * The data related to this event, if any. In the ondata callback,
   * data will be the bytes read from the network; if the binaryType
   * of the socket was "arraybuffer", this value will be of type ArrayBuffer;
   * otherwise, it will be a normal JavaScript string.
   *
   * In the onerror callback, data will be a string with a description
   * of the error.
   *
   * In the other callbacks, data will be an empty string.
   */
  readonly attribute jsval data;
};

