Tivoli Service Desk 6.0 Developer's Toolkit Script Programming Guide

Chapter 11: Networking Concepts

Back to Table of Contents


Introduction

This chapter is designed to introduce the fundamental concepts that are necessary to use the TSD Script networking extension statements to communicate across your network. This chapter also describes special networking concepts and TSD Script networking statements and constants.
These TSD Script statements may be used to customize the source code for your installed applications or to create your own custom TSD Script distributed application.

What you need to know

Although this chapter touches on some fundamental aspects of the TSD Script language and networking principles, it is assumed that you are familiar with both areas. If you are modifying an application, you may want to work with someone who has customized other applications or who has used TSD Script and Developer's Toolkit.

Networking architectures

The statements included with the TSD Script language allow for two distinctive types of networking architectures:

In this chapter, the description of the TSD Script networking services is generally applicable to both architectures. Where differences exist between the architectures, they are stated.

Networking Terminology

There are many terms used to describe the interactions between computers on a network. Although you may be familiar with some or all of these terms, they are defined here specifically in the context of their use with the TSD Script networking extensions.

Bi-directional communication

Bi-directional communication occurs when two machines each play the roles of both client and server. In other words, Machine A (client) can request Machine B (server) to perform some service. Likewise, Machine B can switch roles and become the clientby requesting Machine A to perform some service. See also the definition of reverse connection. See peer-to-peer.

Client

A client is an application that requests a service from a server. An example of a client is a workstation on a network connecting to a file server. The connection is initiated by the client.

Connection

A connection is the logical link between a client and a server.

Event handler

An event handler is a special TSD Script function designed to process asynchronous events. Event handlers run on the server to process network requests for a service.

Handle

Each connection has a handle. The handle contains the information about the client machine and the service that the server is providing.

TSD Script server

An TSD Script server is an TSD Script process running on a networked computer that provides a service.

Local event handler

The local event handler is the event handler operating on the local machine. If this event handler is servicing requests from a different machine, the machine is a server.

NETx statements

The NETx statements, or extensions, are the TSD Script statements that begin with the prefix, NET. These statements were created to allow TSD Script applications to communicate across a network.

Peer-to-peer environment

A peer-to-peer environment is one in which a single machine may play the role of both a client and a server.

Registering

Registering an event handler associates the handler with an event source.

Reverse connection

A reverse connection can be established in a peer-to-peer environment when a server requests a client to perform some serviceeffectively switching the roles of client and server. To handle this communication, a reverse connection is established between the local and the remote server.

Server

A server is a machine that provides a service to a client. An example of a server is a networked printer.

Service

A service is the function performed by the server. If a printer is a server, the service it provides is printing.

Event Handlers

Event handlers are used throughout TSD Script and Developer's Toolkit to support an event-driven environment. In an event-driven environment, an event (such as a keystroke, a mouse click, or a network message) triggers a response by the application (such as opening a new dialog box or selecting an entry in a field). To process events, each application uses event handlers designed specifically for them.

Applications that use event handlers do not have to ask or "poll" for network events. Normally, event handlers "sleep" (aren't active) until an event occurs, then process a request for service.

A single server can have multiple event handlers. Each event handler is designed to provide a specific service, or set of related services, as explained later in this chapter.

Defining event handlers

Event handlers are defined in the routines section of an TSD Script program. Network event handlers must be declared as type NETCONNECTION.

This event handler type is different from the default type, WINDOW. Since the type determines the $Handle that is used, only event handles of type NETCONNECTION can be used with the NETx statements.

NETCONNECTION EVENT TalkConnectEvent( REF whdl: WINDOW ) IS

NetRegister and NetListen Event Handlers

When you define an event handler, you must also register its service, as described in the following sections. Registering an event handler associates the handler with an event source.

There are two different statements that you can use to register an event handler:

Event handlers registered with NetRegister are called NetRegister event handlers. Event handlers registered with NetListen are called NetListen event handlers.

This chapter focuses on the use of NetRegister, which is used frequently for "standard" event handlers. For customizing event handlers, see the "Advanced Statements" section in this chapter.

Registering an event handler and its service

You must register an event handler with the server for it to receive and process requests for service. To register an event handler with the NetRegister statement, use the following syntax:

NetRegister( TalkConnectEvent, 'Talk' ); 

When you register an event handler, you specify the name of the service it provides. A service is a category of actions performed by the event handler.

In the following example, the name of the service defined for the TalkConnectEvent network event handler is Talk.

NETCONNECTION EVENT TalkConnectEvent( REF whdl: WINDOW ) IS
ACTIONS
.
..
END;
NetRegister (TalkConnectEvent, 'Talk');

Using ports with a network connection

In addition to the services noted previously, a port number extension is supported that specifies an IP port. The port number controls:

The default port is 5001, and the default service is asenet/tcp. If the service is in the services file, asenet/tcp is used instead of the default number.

A port number may be specified in the command prompt with the following command:

/p=nnn 

A port number issued from a command prompt overrides both the default port and the default service.

Note: Port numbers must be the same for the client and the server.

Creating a wildcard service

You can create an event handler with a service defined as either a zero-length string ('') or $Unknown. This type of service is called a wildcard service.

When a wildcard service is defined on the server, it services any request specified by the client for which the server cannot find a matching service name.

You can also define a wildcard service on the client. In this case, the server must have a service with the service name of either '' or $Unknown.

Note: You can define a wildcard service only when registering the event handler with the NetRegister statement. (NetListen always uses a wildcard service.)

Templates

When you register an event handler, a template for the service is defined on the server. This template includes information from both the definition of the event handler in the routines section of the code as well as information specified when the event handler was registered.

The template is held in storage until a connection is requested. Then the information in the template is used to instantiate the service for the connection.

Changing an event handler and its template


There are two basic types of changes that you can make to a template:

Any time you need to make changes to a template, you can either re-register the event handler or register its service. When you re-register an event handler, the new parameter values are implemented immediately. All new connections opened for the template will use new values. Existing connections are not affected by the change(s) to the template.

Caution: You must specify the service name exactly as it is specified in the original template. Otherwise, the NetRegister statement creates a new template for the event handler, and the existing template will not be modified.

Stopping an event handler from processing requests

Once a template is created, it becomes immediately and continuously receptive to requests for service. However, a template can be stopped from responding to requests for service at any time. To do this, you must re-register the service with the special event handler $NullHandler:

NetRegister ($Nullhandler, 'service'); 

In this syntax, "service" is the name of the service associated with the event handler you want to stop.

After you re-register the service with $NullHandler, future requests for service from the template are denied, but any existing connections that use the template are not affected.

If you need to restart the server, you must re-register the event handler and its service.

Getting host (server) and service information

An event handler may service connections with many different clients. It may be difficult, simply by looking at the connection handle, to determine the service that is being performed.

Likewise, it may be difficult to determine which server is performing the service or which client is being served. This is especially true for a NetListen event handler, which responds to every service request it receives and which shares its instance data.

TSD Script provides two statements that can be used to obtain information about the host (server) and service from a connection handle:

Because TSD Script supports a client/server architecture as well as a peer-to-peer architecture, the NetGetHostName statement is designed to get information about the remote machine, regardless of whether or not it is playing the role of the server.

If you call the NetGetHostName statement on the client, you will get information about the server. If you call the NetGetHostName statement on the server, you will get the client's name.

Establishing local communication between event handlers

There are probably many NETCONNECTION event handlers on any server. Occasionally, you may need to pass messages between them. Because it is not efficient to send these messages across the network, Developer's Toolkit provides the statement NetLoopBack. NetLoopBack allows you to send a message to a network event handler from your local machine.

Connections

TSD Script networking applications use a connection-based protocol. Interaction between machines on a network occurs through a connection. For a server to provide a requested service to a client, a connection must be opened.
There are three elements in every connection:

It is the combination of these three elements that makes a connection unique. The process of opening and closing a connection involves each of these elements.

Multiple connections can be open between a client and a server. However, a client can have only one connection open for a specific service on a server/port.

Note: If a connection is already open between a client and a specific event handler on a server, requesting a specific service returns the handle of the existing connection.

After you register an event handler and its associated service, the server is ready to receive requests for the specified service.


Opening a connection

This section describes the process of opening a connection and lists the steps for the procedure used to open a connection.

The procedures to open a connection and an explanation of each step follows.

  1. The client sends a connection request to the server by calling the NetConnect statement.
  2. When a client requests a service, the client must specify the exact name of the service that it needs. (The name of the service is defined when the event handler is registered on the server.) There is no comprehensive list of the available services provided by a server and service names are not case-sensitive.

    A port can be specified as part of the service string. If no port is specified, the default is used.

    A client can request a wildcard service by specifying either a zero-length string or $Unknown. In this case, the server must have a service with the service name of either NetListen, or $Unknown to fulfill the request.

    Note: If the client requests a service that is not defined on the server, and if there is a wildcard service or NetListen is defined, the server matches the client's request with the wildcard service.

  3. The client verifies that it can communicate with the server.
  4. If the client cannot communicate with the server, a HOST_UNREACHABLE error code (-13) is returned to the client.

  5. The server determines whether an TSD Script server is listening on the requested (or default) port.
  6. If a TSD Script server is not running, a -13 HOST_UNREACHABLE error code is returned to the client.

  7. If a TSD Script server is running, the server queries itself to determine whether the connection between the client and the TSD Script server is already established.
  8. If the connection has already been established, TRUE is returned to the client. The handle for the connection is also returned.

  9. If there is no open connection for the service, the TSD Script server looks for a template with a service name that matches the service the client requested, and is associated with the port on which the request was received.
  10. If a matching service name is found, the server returns a handle to the client. The handle points to a copy of the template that provides the service. When the client receives the handle, it can continue with its processing.

  11. If there is no matching service, the server determines whether a template with a wildcard service has been registered, and is associated with the port on which the request was received.
  12. If the server finds a wildcard service, the server returns the handle to the client. The handle points to a copy of the template that provides the wildcard service. When the client receives the handle, it can continue with its processing.

  13. If there is no template with a wildcard service, and the request was received on the default port, the server checks for the presence of a NetListen event handler.
  14. If a NetListen event handler is found, a handle is returned to the client that describes the connection to the client machine. If found, the handle points directly to the NetListen event handler. When the client receives the handle, it continues processing event data.

    If a NetListen event handler is found, go to step 10. If a NetListen event handle is not found, proceed to step 8.

  15. If a matching service is still not found, NetConnect returns an error code (-16), indicating that the service requested is not supported on the targeted server.
  16. If a NetRegister service is found, a NetRegister connection is created from the template with its own copy of the instance data. The event handle receives a $MsgCreate message.
  17. The server sends the event handler a $MsgNetConnect message to open the connection on the server side.

Once $MsgNetConnect is processed on the server, the connection is open and the service can be used.

Closing a connection

The process of closing a connection is usually initiated by the client. However, the server can also initiate the closure. In either case, the NetClose statement is used to close the connection.

Note: If either the client or the server goes down, the connection between them is dissolved. To re-establish the communication between the machines, you must reopen the connection.

Client-initiated closure

When a client closes a connection, the following process occurs:

  1. The client closes the connection.
  2. The server detects that the connection is closed. The server responds by sending the event handler two messages:
  3. The handle is marked as closed.

Note: If the event handler is a NetListen event handler, there is no instance data specifically defined for the connection. The closure process is completed when the handle is marked as closed. No $MsgNetDestroy message is sent.

If the client or server program end, or if there is a break in the network, steps 2 and 3 still occur.

Server-initiated closure

If the server initiates the closure of the connection, no communication exists from the server back to the client.

The next time the client attempts to communicate with the server, it detects the closure and generates an error message such as "invalid handle."
In a peer-to-peer environment NetClose closes both the client and server connection.

Instance Data

Instance data is user-defined TSD Script data that is associated with a connection. Instance data is created when the connection is created and is destroyed when the connection is closed.

Event handler references to instance data

The event handler receives a reference to the instance data with every message for the connection. The instance data stores information specific to the connection.

When you register an event handler with NetRegister, you can specify an initial value for the instance data of that event handler. All connections that are opened for the template receive a copy of the instance data initialized to the value you specified, or to $Unknown if no initial value is provided.

When you specify the instance data, remember the following.

For example:

connectionData is Record
     callCount = INTEGER;
.
.
.
END; 
NETCONNECTION EVENT MyEvent (REF data: ConnectionData);
ACTIONS
    When $Event IS $MsgCreate Then
        data.callCount=1;
        .
        .
        . 
     END;
END;
StmtData : ConnectionData;
NetRegister( MyEvent {StartDate}, 'Service');

Initializing the instance data

When a connection is opened, the instance data defined for the event handler is instantiated in the copy of the template for the connection and is assigned its initial value. This process is called initialization.

$Unknown instance data

If you set the value of the instance data in the template to $Unknown, this means that initialization does not occur.

Initialization also does not occur unless you set a value for the initial value of the instance data. If you do not set a value, the initial value is assumed to be $Unknown.

Multiple connections for an event handler

There may be multiple connections open for a single NetRegister event handler. Each of these connections has its own copy of the instance data.

Blocking and Non-blocking Statements

A client can send a request to a server at any time, regardless of whether the server is currently in the process of handling a previous request or not. Depending on how quickly the client requires a response from the server, and whether the client requires data to be returned from the server, it may send its request with either a blocking or non-blocking statement:

When a server receives requests, it adds them to its queue. As it is able, the server processes the requests in the order in which they were received. (In some cases, the server may place blocking messages in the queue in front of non-blocking messages). Depending on the condition of the network, it may take some time before the server can service a request.

Blocking statements

If the statement sent to the server is a blocking statement, no information is returned to the client until the entire process can be completed on the server.

SendMessage is the only blocking statement in TSD Script.

To prevent deadlock between a client and server, only one SendMessage can be active on the connection at any one time.

Non-blocking statements

If the statement sent to the server is a non-blocking statement, the server returns a reply to the client which effectively says, "I have your request" when the statement is added to the queue. The client can then continue its processing.

There are several non-blocking statements:

Choosing the type of statement to send

You can choose either blocking or non-blocking statements to communicate with the server. Choosing either type has some risks that you need to be aware of:

Handles

In TSD Script and Developer's Toolkit, handles are used extensively to keep track of window and network activity.

Handles are required for connections with either the SendMessage or PostMessage statements. These statements are blocking and non-blocking, respectively. This characteristic determines the behavior of the client and the server.

Opening a handle

The server opens a handle when it locates the event handler template with the service that matches the service requested by the client. The handle is contained in the $Handle parameter and passed to the event group servicing the connection.

Closing a handle

The server marks a handle as closed when the server closes its end of the connection. If you attempt to access a closed connection, you receive an error message (Invalid_Handle).

Establishing Bi-Directional Communication

The TSD Script NETx statements can be used in both client/server and peer-to-peer architectures. To handle these different architectures, there are two formats for the NetConnect statement.

Client/server

In the client/server architecture, the client must specify a host name and service so that the server can respond to the client's request and return the service so that the server can respond to the client's request and return the requested service.

FUNCTION NetConnect(REF hndlHost: NETCONNECTION,
                    .VAL hostName: STRING, 
                    . VAL service: STRING
                    .): INTEGER;

Peer-to-peer

To respond to the client in peer-to-peer architecture, the server must open a return connection. The peer-to-peer format is really a shortcut for creating a return connection. This format is optional; you may achieve the same result by using the client/server format.

FUNCTION NetConnect( VAL hndlHost: NETCONNECTION
                    ): INTEGER;

TSD Script handles for peer-to-peer connections

You need only one handle for a peer-to-peer connection. The handle will contain all of the data about the connection.

For a detailed description of NetGetHostName or NetGetService, see the next chapter.

Use the $Handle constant to send a reply to a remote server. You can initialize a return connection with the following line:

NetConnect( $Handle );

Advanced Statements: NetListen and NetAccept

So far, this chapter focused on the "standard" method of creating and registering an event handler using the NetRegister statement. For applications that require more control over connections, TSD Script provides an alternative set of statements that can be used together to register an event handler. These statements are:

NetAccept event handlers are very similar to NetRegister event handlers.

Note: You do not have to use either the NetListen or NetAccept statements to achieve a fully functional networked application.

Table of event handler differences

This table summarizes the differences between NetRegister and NetListen event handlers.

Because NetListen doesn't create new instance data for each connection, the process of opening a connection through NetListen is slightly faster.

NetListen is well suited to lightweight services that do not require a context to be maintained between messages.

Comparison Item NetRegister NetListen
Number of Event Handlers There can be many NetRegister event handlers running on a server simultaneously. There can be only one NetListen event handler defined for a server.
Registered Service A NetRegister event handler is registered with a specific service. The client must request that service name exactly to get a service match with the appropriate template. A NetListen event handler does not have a specific service associated with it. A service match is made with the NetListen event handler only if there are no other matching templates on the server.
Template When you register a NetRegister event handler, a template of it is made. The template contains all of the connection specific information. There is no template created when you register a NetListen event handler. The connection-specific information must be maintained by the application.
Instance Data Each connection has its own copy of the instance data. There is one set of instance data defined for the event handler. Every connection opened for the event handler shares that instance data.
Ports The service may use an alternate port. The service may only use the default port.

Uses for NetListen and NetRegister event handlers

You might have both a NetListen and a NetRegister event handler running on a server at the same time. Because a client does not know how a request is serviced, the client cannot specifically request which event handler is used.

NetListen event handlers are used for services that do not require context information to be maintained for a connection. NetListen event handlers require slightly less server resources and create connections slightly faster than NetRegister event handlers.

The client's request is matched with a NetListen event handler only if no other match (including a wildcard template) can be found. The client sends the service name to the NetListen event handler on the server. The NetListen event handler must query the handle for service with NetGetService.

The client, however, has no guarantee that the service is supported by the server.

NetListen connections

There may be multiple NetListen connections open simultaneously, since each connection shares the same instance data with other open connections. Therefore, when you close a NetListen connection, the instance data is not destroyed.

When you close a NetListen connection, you need to clean up the resources for the connection that is being closed.

Handles

The handle for each NetListen connection has the information about the specific type of service that is being requested by the client.

The NetListen event handler does not associate instance data with each connection. Instead, you must keep track of each connection and its activity. The ability to track individual connections is an added benefit of using the NetListen statement to register event handlers.

Assigning specific instance data for a NetListen connection

Each connection opened for NetListen shares the copy of instance data defined for the NetListen event handler. If you want to associate a specific set of instance data with one of your open NetListen connections, you can call the NetAccept statement for that connection.

Note: NetAccept can only be called for a NetListen connection. You access the connection using its handle. NetAccept can also associate a new event handler with the connection.

The instance data you associate with the connection is not used with any other connections that are currently open or that might be opened in the future for the NetListen event handler. Once you call NetAccept, the connection is altered.

All requests for the same host/service pair go directly to the new event handler.

Note: You may find it easier to use NetRegister, because the combination of NetListen and NetAccept achieves the same result.

Example TSD Script Talk Program

This example illustrates how to set up a simple talk program between two networked computers. This program demonstrates the interaction between two machines in a peer-to-peer environment.

KNOWLEDGEBASE NetTalk; 
CONSTANTS
    menuList IS { 
      '~File',
          'e~Xit', '',
      '~Host',
          '~Open', '',
      '~Help',
          '~About', ''
   }: LIST OF STRING;
   MsgUserChar IS $MsgUser;
   MsgRemoteChar IS $MsgUser + 1;
   MsgTalkClose IS $MsgUser + 2; 
ROUTINES 
EVENT TalkMainEvent;
FUNCTION CreateTalkWindow( VAL host: NETCONNECTION ) : WINDOW;
PROCEDURE NetTalkMain; 
PRIVATE
TYPES 
    TALK_RECORD IS RECORD
        xLen: INTEGER; -- Width of window in characters 
        yLen: INTEGER; -- Height of window in characters
        whdlMe: WINDOW; -- Window where local input
                     is displayed
        whdlYou: WINDOW; -- Window where remote input 
                     is displayed
      host: NETCONNECTION; -- Handle host
END;
PANNEL_DATA IS RECORD
  whdlParent: WINDOW;
  curX: INTEGER; -- X location of cursor on the window
  curY: INTEGER; -- Y location of cursor on the window
  lines: LIST OF STRING; -- List of all lines being edited
END; 
ROUTINES 
NETCONNECTION EVENT TalkConnectEvent(REF whdl: WINDOW )IS 
VARIABLES
    result : INTEGER; 
ACTIONS
  WHEN $Event IS $MsgNetConnect THEN
  -- Create a talk window.
  -- Create a connection to service this talk session
  result := NetConnect( $Handle );
  IF result < 1 THEN
      WinMessageBox(whdl,'Error',$MBOk + $MBIconError, 
                   'Connection failed ERROR ' & result );
    Exit( 0 );
  END;
  whdl := CreateTalkWindow( $handle );
  IF whdl = $UNKNOWN THEN
     WinMessageBox(whdl,'Error',$MBOk + $MBIconError, 
                  'Window creation failed' );
   NetClose( $Handle );
   Exit( 0 );
  END;
ELSWHEN MsgRemoteChar THEN
  -- Pass the character from the remote machine to the
     talk window 
  SendMessage( whdl, MsgRemoteChar, $KeyCode );
ELSWHEN MsgTalkClose THEN
  NetClose( $Handle );
ELSWHEN $MsgNetClose THEN
  -- When the windows close on the remote machine
    clean up here
  SendMessage( whdl, $MsgClose );
  NetClose( $Handle );
  END;
END; 
EVENT TalkMainEvent IS
VARIABLES
  host : NETCONNECTION;
  hostName : STRING;
  result : INTEGER;
ACTIONS
  WHEN $Event IS $MsgCreate THEN
    WinSetMenuBar( $Handle, menuList );
  ELSWHEN $MsgMenu THEN
    WHEN $MenuSelection IS 101 THEN
      SendMessage( $Handle, $MsgClose );
    ELSWHEN 201 THEN
        WinEditField($Desktop, hostName, 0, 0, 40,
                    'Enter host name', 
                    BitOr($WinTitle, $WinBorder, 
                         $WinAutoPos ) );
       -- Create a talk connextion to hostname
       result := NetConnect( host, hostName, 'Talk' );
    IF result <> 1 THEN
        WinMessageBox($Handle, 'Error', 
                      $MBOk + $MBIconError, 
                      'Connection failed
                      ERROR ' & result );
    END;
  END;
 END;
END;
EVENT TalkPannelEvent( REF pannelData: PANNEL_DATA ) IS
ACTIONS
  WHEN $Event IS $MsgCreate THEN
    pannelData.curX := 1;
    pannelData.curY := 1;
    ListInsert( pannelData.lines, '' );
  ELSWHEN $MsgPaint THEN
    -- Clear window, and re display contents
   WinSetFont($Handle, 'System Monospaced', 10, 0 );
   WinClear($Handle );
   WinWriteLn($Handle, pannelData.lines );
  ELSWHEN $MsgChar THEN
     -- The parent window processes all characters
        entered
     SendMessage(pannelData.whdlParent, $MsgChar, 
                $KeyCode );
  ELSWHEN MsgUserChar THEN
    WHEN $KeyCode IS $KeyReturn THEN
      -- Enter key is a new line
      pannelData.curX := 1;
      pannelData.curY := pannelData.curY + 1;
      ListInsert(pannelData.lines, '' );
  ELSE
     -- Add character to current line, and display it
     WinSetFont($Handle, 'System Monospaced', 10, 0 );
     WinGotoXY($Handle, pannelData.curX,
               pannelData.curY );
  WinWrite($Handle, Char( $KeyCode ) );
           pannelData.curX := pannelData.curX + 1;
           pannelData.lines[ $CURRENT ] := 
             StrInsert(pannelData.lines [ $CURRENT ],
                       Char( $KeyCode ), 1000 );
         END;
       END;
     END; 
     EVENT TalkEvent( REF talkData: TALK_RECORD ) IS
     VARIABLES
       pannel : PANNEL_DATA;
       yLen : INTEGER; 
     ACTIONS
       WHEN $Event IS $MsgCreate THEN
        -- Create 2 display panels for local, and remote
           characters and pass in parent
         pannel.whdlParent := $Handle;
         yLen := talkData.yLen / 2;
         WinCreate($Handle, talkData.whdlMe,
                   TalkPannelEvent{ pannel }, 
                   0, 0, talkData.xLen, yLen, '',
                   $WinField );
         yLen := talkData.yLen - yLen;
         WinCreate($Handle, talkData.whdlYou, 
                    TalkPannelEvent{ pannel }, 
                    0, yLen + 1, talkData.xLen, yLen,'', 
                    $WinField );
   ELSWHEN $MsgDestroy THEN
      PostMessage( talkData.host, MsgTalkClose );
   ELSWHEN $MsgSize THEN
      -- Position and size panels to fit window when
         it is resized
     talkData.xLen := $EventParm( 1, INTEGER );
     talkData.yLen := $EventParm( 2, INTEGER );
     yLen := talkData.yLen / 2;
     SendMessage(talkData.whdlMe,$MsgSetSize 
                 talkData.xLen, yLen);
     yLen := talkData.yLen - yLen;
     SendMessage(talkData.whdlYou,$MsgSetSize,
                 talkData.xLen,yLen );
     SendMessage(talkData.whdlYou,$MsgMove,1,
                 yLen + 1 );
  ELSWHEN $MsgChar THEN
    -- Send local characters to top pannel for display
    SendMessage(talkData.whdlMe, MsgUserChar,
                $KeyCode );
    -- also send character to remote host to display
    PostMessage(talkData.host, MsgRemoteChar,
                $KeyCode );
  ELSWHEN MsgRemoteChar THEN
    -- Send remote character to bottom pannel for display
    SendMessage(talkData.whdlYou, MsgUserChar,
               $KeyCode );
  ELSWHEN $MsgPaint THEN
    WinClear( $Handle );
  END;
END; 
FUNCTION CreateTalkWindow( VAL host : NETCONNECTION ) : WINDOW IS
VARIABLES
  whdlNetTalk: WINDOW;
  talkData: TALK_RECORD;
  result: INTEGER; 
ACTIONS
  talkData.host := host;
  result := WinCreate($Desktop, whdlNetTalk, 
                      TalkEvent{talkData},
                      0, 0, 0, 0,
                      NetGetHostName(host), 
                      BitOr($WinBorder, 
                            WinTitle,
                            $WinResize,
                            $WinSysMenu,
                            $WinAutoSize, 
                            $WinAutoPos,
                            $WinTaskList));
  IF result < 1 THEN
    WinMessageBox($Desktop, 'Error', 
                  $MBOk + $MBIconError,
                  'Cannot create talk main
                  window. 
                  Error: '&result );
  END;
  EXIT( whdlNetTalk );
END; 
PROCEDURE NetTalkMain IS
VARIABLES
  whdlNetTalk: WINDOW;
  result: INTEGER; 
 ACTIONS
  result := WinCreate($Desktop, whdlNetTalk,
                      TalkMainEvent, 0, 0, 
                      40, 0,
                      'Network talk program', 
                      BitOr($WinBorder,
                            $WinTitle,
                            $WinResize,
                            $WinSysMenu,
                            $WinMenu,
                            $WinTaskList));
 IF result < 1 THEN
   WinMessageBox($Desktop, 'Error',
                 $MBOk + $MBIconError,
                 'Cannot create talk 
                 main window.
                 Error: ' &result );
 END;
 NetRegister( TalkConnectEvent, 'Talk' );
 WinWait( whdlNetTalk );
END;

Tivoli Service Desk 6.0 Developer's Toolkit Script Programming Guide

Back to Table of Contents

Copyright