+ All Categories
Home > Documents > Application Initialization using Avaya AE Services TSAPI ... · Application Initialization using...

Application Initialization using Avaya AE Services TSAPI ... · Application Initialization using...

Date post: 01-May-2018
Category:
Upload: duongminh
View: 275 times
Download: 3 times
Share this document with a friend
78
Application Initialization using Avaya AE Services TSAPI SDK for Windows A Devconnect Tutorial Table of Contents Section 1: Avaya AE Services and TSAPI Overview ....................... 3 Section 2: Session Management .............. 7 Section 3: Control Services and the Request/Response Model.... 18 Section 4: Event Handling...................... 20 Section 5: Private Data ........................... 33 Section 6: Setting Up the TSAPI Programming Environment ................................................ 43 Section 7: A Practical Example............. 46 Appendix A: Notes...................................... 51 Appendix B: Complete Example Code .. 54 Appendix C: References ............................77 Overview Implementing a telephony-enabled application using Avaya Telephony Services Application Programming Interface (TSAPI) requires an understanding of TSAPI core concepts of Session and Event Management, control services, and private data. This tutorial provides an overview of the TSAPI essentials, using code samples to demonstrate how to write a telephony-enabled application for the Avaya Communication Manager environment using the interfaces provided by the Avaya TSAPI implementation. INTENDED AUDIENCE This tutorial is intended for programmers who have a working knowledge of C/ C++ programming on Windows platform and wish to implement telephony- enabled applications in an Avaya Aura™ Communication Manager environment. This tutorial is not meant to be an exhaustive introduction to TSAPI; refer to Reference [1] for a complete understanding of the Avaya TSAPI implementation. After completing this tutorial, the reader should be able to: Understand the TSAPI concepts. Initialize a telephony-enabled application using the Avaya TSAPI library. Open a Session with TSAPI Service with (or without) Private Data negotiation. Receive events from TSAPI Service. Start and stop monitoring a device. Handle error conditions. Close the Session with TSAPI Service. Abort the Session with TSAPI Service. DOCUMENT ORGANIZATION This tutorial begins with an overview and description of all the required TSAPI concepts, and makes the reader familiar with the TSAPI library. It then 1 DEVCONNECT TUTORIAL avaya.com ISSUE 1.0 • SEPTEMBER 2009
Transcript
Page 1: Application Initialization using Avaya AE Services TSAPI ... · Application Initialization using Avaya AE Services TSAPI SDK for Windows A Devconnect Tutorial Table of Contents ...

Application Initialization using Avaya AE Services TSAPI SDK for Windows A Devconnect Tutorial

Table of Contents

Section 1: Avaya AE Services and

TSAPI Overview .......................3

Section 2: Session Management ..............7

Section 3: Control Services and the

Request/Response Model .... 18

Section 4: Event Handling ...................... 20

Section 5: Private Data ........................... 33

Section 6: Setting Up the TSAPI

Programming Environment

................................................ 43

Section 7: A Practical Example ............. 46

Appendix A: Notes ...................................... 51

Appendix B: Complete Example Code .. 54

Appendix C: References ............................77

Overview

Implementing a telephony-enabled application using Avaya Telephony Services

Application Programming Interface (TSAPI) requires an understanding of TSAPI core

concepts of Session and Event Management, control services, and private data.

This tutorial provides an overview of the TSAPI essentials, using code samples

to demonstrate how to write a telephony-enabled application for the Avaya

Communication Manager environment using the interfaces provided by the

Avaya TSAPI implementation.

INTENDED AUDIENCE

This tutorial is intended for programmers who have a working knowledge of C/

C++ programming on Windows platform and wish to implement telephony-

enabled applications in an Avaya Aura™ Communication Manager environment.

This tutorial is not meant to be an exhaustive introduction to TSAPI; refer to

Reference [1] for a complete understanding of the Avaya TSAPI implementation.

After completing this tutorial, the reader should be able to:

• Understand the TSAPI concepts.

• Initialize a telephony-enabled application using the Avaya TSAPI library.

• Open a Session with TSAPI Service with (or without) Private Data negotiation.

• Receive events from TSAPI Service.

• Start and stop monitoring a device.

• Handle error conditions.

• Close the Session with TSAPI Service.

• Abort the Session with TSAPI Service.

DOCUMENT ORGANIZATION

This tutorial begins with an overview and description of all the required

TSAPI concepts, and makes the reader familiar with the TSAPI library. It then

1DEVCONNECT TUTORIAL

avaya.com

ISSUE 1.0 • SEPTEMBER 2009

Page 2: Application Initialization using Avaya AE Services TSAPI ... · Application Initialization using Avaya AE Services TSAPI SDK for Windows A Devconnect Tutorial Table of Contents ...

avaya.com

2

discusses how to set up the environment for the TSAPI application, and closes with a complete practical source

code example which makes use of all the TSAPI concepts covered in prior chapters.

• Chapter 1: Avaya AE Services and TSAPI Overview

This chapter provides the reader with a brief understanding of Avaya Application Enablement (AE) Services,

the purpose of the Avaya TSAPI library, and its basic capabilities. In this chapter, the reader will find brief

definitions of the concepts that are essential to develop a TSAPI application.

• Chapter 2: Session Management

This chapter explains:

a) The meaning of Session in TSAPI terminology.

b) Why a Session is required.

c) How a Session can be opened.

d) How a Session can be closed.

• Chapter 3: Control Services and the Request/Response Model

This chapter describes the types of Control Services, their usage and the request/response model that TSAPI supports.

• Chapter 4: Event Handling

This chapter explains the types of events, different ways to receive events, and the process to extract

information from events.

• Chapter 5: Private Data

This chapter provides basic information on handling Private Data including negotiating, and sending and

receiving Private Data.

• Chapter 6: Setting up the TSAPI Programming Environment

This chapter guides the reader in setting up and configuring the programming environment required to write and

run a TSAPI application.

• Chapter 7: A Practical Example

The final chapter includes a step by step guide demonstrating a C++ implementation of a telephony-enabled

application for a Microsoft Windows platform using the Avaya TSAPI SDK. The examples provided in this tutorial

are kept as simple as possible so as to help the reader understand key concepts which can then be applied for

building advanced applications.

Appendices, including notes, a complete source code listing, and references are also included.

Page 3: Application Initialization using Avaya AE Services TSAPI ... · Application Initialization using Avaya AE Services TSAPI SDK for Windows A Devconnect Tutorial Table of Contents ...

avaya.com

3

PREREQUISITES

Readers are assumed to have C++ programming experience and knowledge of Avaya Aura Communication Manager

and Avaya Application Enablement (AE) Services.

The Avaya TSAPI SDK is required to develop a TSAPI application. The Avaya TSAPI Client library is required to

run a TSAPI application. Both the TSAPI Client and TSAPI SDK need to be installed and configured properly on

the machine(s) on which the TSAPI application is to be developed and/or executed. Please refer to Reference

[2] for information on how to install and configure the Avaya TSAPI Client and the TSAPI SDK. Information on

downloading or obtaining the AE Services TSAPI Client and TSAPI SDK is available on the DevConnect Portal.

See www.avaya.com/devconnect (valid DevConnect ID is required to access certain materials).

ACRONYMS USED IN THIS TUTORIAL

Acronym MeaningAE Services Avaya Application Enablement Services

TSAPI Telephony Services Application Programming Interface

CTI Computer Telephony Integration

SDK Software Development Kit

ECMA European Computer Manufacturers Association

API Application Programming Interface

CSTA Computer-Supported Telecommunications Applications

Table 1: List of acronyms used in this tutorial

Section 1: Avaya AE Services and TSAPI Overview

This chapter describes the underlying platform and services that enable developers to write telephony-enabled

applications and the usage of the Avaya software suite. This chapter also helps the reader to understand the role of

each of the components described below in supporting Computer Telephony Integration (CTI).

1.1 AVAYA AURA™ COMMUNICATION MANAGER

Avaya Aura Communication Manager is Avaya’s flagship IP Telephony software platform. It contains robust call

processing capabilities, advanced workforce productivity and mobility features, built-in conferencing and contact

center applications, and support for a variety of wired and wireless end-user communication devices. Avaya Aura

Communication Manager is the call processing software that runs on Avaya’s servers. Communication Manager

processes call requests and allows the user to retrieve and use call information.

Communication Manager offers a variety of first and third-party call control capabilities and event notifications

APIs, although these are not directly exposed for application development. It is through Avaya Application

Enablement (AE) Services that the capabilities of the Communication Manager APIs are exposed as high level

standards based application programming interfaces (APIs).

Page 4: Application Initialization using Avaya AE Services TSAPI ... · Application Initialization using Avaya AE Services TSAPI SDK for Windows A Devconnect Tutorial Table of Contents ...

avaya.com

4

1.2 APPLICATION ENABLEMENT (AE) SERVICES

AE Services is a server-based software application that provides connectivity between client applications and Avaya

Communication Manager. AE Services incorporates a number of discrete services which provide high-level abstractions

of the Communication Manager API. These AE Services APIs allow other software products to interface with

Communication Manager using services provided by Avaya AE Services. The APIs allow software developers to create

their own client applications that interact with, and leverage the capabilities of, Avaya Communication Manager.

AE Services enables software developers to write client applications using a wide variety of programming languages

such as C, C++, Java, etc.

Figure 1 below depicts a high level view of how AE Services, Avaya Communication Manager, Avaya endpoints and

client communication applications align:

Figure 1: AE Services server architecture

AE Services offers several different types of services, each exposed through different combinations of APIs and

SDKs. These include:

• System Management capabilities, exposed as web services;

• Basic Telephony services, also exposed as Web Services;

Page 5: Application Initialization using Avaya AE Services TSAPI ... · Application Initialization using Avaya AE Services TSAPI SDK for Windows A Devconnect Tutorial Table of Contents ...

avaya.com

5

• Device, Media and Call Control services, exposed through Java, XML or .Net interfaces;

• And TSAPI services, exposed via a TSAPI client library using a C/C++ API, or via a Java Telephony API (JTAPI)

client library for Java-based application development.

Each of these AE Services APIs offer slightly different levels of functionality, and the choice of which one is most

appropriate to use is dependent upon the needs of the application under development (Table 2):

Programming Language, Protocol or Web ServicesFunctionality Java .NET C and C++ Other / XML Web Services

Advanced third- party call control

JTAPI TSAPI

Basic third-party call control

DMCC Java API

DMCC .NET API

DMCC XML protocol

DMCC XML protocol

Simple call creation and maintenance

Telephony

Physical device control

DMCC Java API

DMCC .NET API

DMCC XML protocol

DMCC XML protocol

Media control DMCC Java API

DMCC .NET API

DMCC XML protocol

DMCC XML protocol

Communication Manager system management

System Management Service

Table 2: Comparison of AE Services SDKs

Not explicitly shown in Figure 1 is an LDAP store, containing the Security Database and CTI User credentials. This

information is accessed by the TSAPI Service and used for the purpose of managing application’s access of AE

Services device monitoring and control.

1.3 ABOUT TSAPI

The Telephony Services API (TSAPI) is based on international standards for CTI telephony services. Specifically,

the European Computer Manufacturers Association (ECMA) CTI standard definition of Computer-Supported

Telecommunications Applications (CSTA) is the foundation for TSAPI. The CSTA standard is a technical agreement

reached by an open, multi-vendor consortium of major switch and computer vendors. Since CSTA services and

protocol definitions are the basis for TSAPI, TSAPI provides a generic, switch-independent API.

1.3.1 TSAPI for Communication Manager

TSAPI for Avaya Communication Manager is an implementation of the generic TSAPI specification. Stated another

way, TSAPI for Avaya Communication Manager is a switch-specific API that helps C and C++ programmers to

implement CTI in the Avaya Communication Manager environment.

Page 6: Application Initialization using Avaya AE Services TSAPI ... · Application Initialization using Avaya AE Services TSAPI SDK for Windows A Devconnect Tutorial Table of Contents ...

avaya.com

6

TSAPI for Communication Manager is a library interface that is designed exclusively for use with Avaya

Communication Manager.

1.3.2 TSAPI Service

TSAPI Service is one of the services that run on AE Services server. TSAPI Service acts as a server for the TSAPI

Client running on the client machine. TSAPI Service receives requests from the TSAPI client, processes these

requests with the help of Communication Manager and returns the response back to the TSAPI Client.

1.3.3 TSAPI Client

The TSAPI Client provides applications with access to Avaya Communication Manager’s call processing services.

The primary component of the TSAPI Client is the TSAPI library, which is a C/C++ library of function calls

that enables an application to request Computer-Supported Telecommunications Applications (CSTA) services.

Additionally, the TSAPI Client provides access to Avaya Private Data, which extends the CSTA supported

capabilities by providing access to specialized features of Avaya Communication Manager.

1.4 ARCHITECTURE OF A TYPICAL TSAPI APPLICATION

A TSAPI application uses the TSAPI Client library which is a C/C++ based client-side interface of TSAPI Service.

The TSAPI Client library establishes a connection with TSAPI Service, sends service requests and receives

responses, on behalf of the client application.

TSAPI provides third party call control capabilities provided by Avaya Communication Manager. These third party

call control capabilities include:

• The ability to make, monitor, answer, transfer, hold, retrieve, deflect, conference, and drop calls.

• The ability to monitor station and Vector Directory Number (VDN) devices for call activity.

• Control and interaction of calls in vector processing, predictive dialing and call classification, or skill-based routing.

• Providing a snapshot of a device which returns information regarding the calls on that device, and a snapshot of

a call which returns information regarding the parties involved in the call.

• Performing logical services such as Agent login/logout, Agent state and device feature control.

• Monitoring ACD (Automatic Call Distribution) Split devices for Agent login/logout events.

Page 7: Application Initialization using Avaya AE Services TSAPI ... · Application Initialization using Avaya AE Services TSAPI SDK for Windows A Devconnect Tutorial Table of Contents ...

avaya.com

7

Figure 2: Architecture of TSAPI Application

Figure 2 depicts how the TSAPI Client library connects the TSAPI applications to TSAPI Service. Note that it is

possible to leverage one instance of the TSAPI Client Library on a server in support of multiple applications, as

shown on Server 1 (machine 1) where two TSAPI applications are running. Both the applications use the same

version of the TSAPI Client library. On Server 2 (machine 2), a single TSAPI application is running, and all three

applications (across both machines) are invoking a common TSAPI Service executing on Avaya AE Services. API

Control Services (ACS) streams are used to manage the interactions with TSAPI Service running on the AE Services

server for passing maintaining sessions and handling event queues.

Section 2: Session Management

This chapter describes ‘Session’ as used with Avaya TSAPI applications, why a Session is required, how does a

TSAPI application open a Session with TSAPI Service to receive data and events, and how to close a Session.

Like any client-server based application, the TSAPI application (i.e., the client) needs to first establish a

communication channel with TSAPI Service before requesting any services from it. This communication channel

is then used to send and receive information by the TSAPI application. This communication channel is called

‘Session’ in general terms. A Session is a logical entity and represents a dedicated link between two parties, one

who establishes the Session (client) and the other (server) who accepts it. Once a Session is established, both the

parties can send and receive data on this communication link. A Session exists until it is either closed explicitly

(by a close request) or closed due to a problem (e.g. loss of network connectivity).

Avaya TSAPI refers to this communication channel as a “stream”. To access any services from TSAPI Service,

an application must first open a stream (or Session). The opened stream establishes a logical link between the

application and Communication Manager (via AE Services).

Page 8: Application Initialization using Avaya AE Services TSAPI ... · Application Initialization using Avaya AE Services TSAPI SDK for Windows A Devconnect Tutorial Table of Contents ...

avaya.com

8

A TSAPI application requires an advertised service name for opening a stream. The TSAPI application can read

the advertised service name from a file (e.g. .ini file), or query the AE Services server using acsEnumServerNames()

method to get the list of advertised service names. Refer to Section 2.1.1 to know more about the

acsEnumServerNames() method.

2.1 ACQUIRING THE NAME OF AN ADVERTISED SERVICE

An advertised service (sometimes referred as advertised server) represents a symbolic name for a communication

path between AE Services server and Communication Manager. A TSAPI application will need to choose the

communication path through which AE Services server will route requests to Communication Manager. TSAPI

provides the acsEnumServerNames() method that can be used by a TSAPI application to get all the advertised

services of the given type, offered by AE Services server.

When this method is invoked by the application, the TSAPI Client library reads the Fully Qualified Domain Name

(FQDN) or IP addresses of AE Services server(s) from the TSAPI Client configuration file (i.e., TSLIB.INI). Using

these FQDN or IP addresses, the TSAPI Client library queries each AE Services server for advertised services of a

specific stream type.

Using the acsEnumServerNames() method, the user can specify a callback method that will be called for each

service name. For each advertised service name returned by each AE Services server, the TSAPI Client library

invokes the callback method with the serverName parameter set to the advertised service name. Both callback and

acsEnumServerNames() methods are described below.

2.1.1 EnumServerNames Callback Method

The application need to implement a callback method which has a specific signature (Code Snippet 1).

EnumServerNamesCB Method’s Signature:

typedef Boolean (*EnumServerNamesCB)( char *serverName, /* INPUT */

unsigned long lParam); /* INPUT */

Code Snippet 1: Enum Server NamesCB Method’s Signature

EnumServerNamesCB Method’s Parameters:

• serverName: A null-terminated string representing an advertised service name.

• lParam - A user-defined parameter which is passed through acsEnumServerNames() method.

Note: The application can choose any name for the callback method as long as the signature matches the

signature described above.

Page 9: Application Initialization using Avaya AE Services TSAPI ... · Application Initialization using Avaya AE Services TSAPI SDK for Windows A Devconnect Tutorial Table of Contents ...

avaya.com

9

EnumServerNamesCB Method’s Return Values:

The callback method needs to return a boolean value. When the callback method returns false, the TSAPI client

will not call the callback method with other service names, whereas true return value indicates that the TSAPI

client can continue to call the callback method with the next service name.

2.1.2 acsEnumServerNames Method

acsEnumServerNames Method’s Signature:

RetCode_t acsEnumServerNames( StreamType_t streamType, /* INPUT */ EnumServerNamesCB callback, /* INPUT */

unsigned long lParam); /* INPUT */

Code Snippet 2: acsEnumServerNames Method’s Signature

acsEnumServerNames Method’s Parameters:

• streamType - Indicates the type of stream requested. Currently, only a stream of type ST_CSTA is supported.

• callback - This is a pointer to a callback method which will be invoked for each of the enumerated server

names, along with the user-defined parameter lParam. If the callback method returns FALSE (0), enumeration

will terminate.

• lParam - A user-defined parameter which is passed on each invocation of the callback method. The application can

use this parameter to pass any value to the callback method when the Client library invokes the callback method.

acsEnumServerNames Method’s Return Values:

A positive return value indicates success and a negative return value indicates failure. There is no confirmation

event for this method. The positive return value is:

• ACSPOSITIVE_ACK: The method completed successfully as requested by the application. No errors were detected.

Possible errors are (negative return value):

• ACSERR_UNKNOWN: The request has failed due to unknown network problems.

• ACSERR_NOSERVER: The request has failed because the Client library is failed to locate one of the AE Services

server’s IP address on the network. This error can arrive if any of the AE Services server’s IP address is not

configured properly.

Page 10: Application Initialization using Avaya AE Services TSAPI ... · Application Initialization using Avaya AE Services TSAPI SDK for Windows A Devconnect Tutorial Table of Contents ...

avaya.com

10

acsEnumServerNames Code Example:

// Callback method that will be called for each advertised service name.// szServiceName method parameter will be set to advertised service name or Tlink// when callback method is called. // lParam will be set to the value of user defined variable provided in// acsEnumServerNames method call.// Return FALSE to stop receiving callback for rest of the service names. Boolean DisplayServerNames(char* szServiceName, unsigned long lParam) { Boolean bReturnValue = FALSE;

if(strcmp(szServiceName, "") != 0) {

// Service name is printed on console here for simplicity, other applcations// can store this value into a map or any other data structure// and use it later as per application requirement. // Refer complete example code to see storing service name in a map.

cout << "Service Name: " << szServiceName;

// Return TRUE so that the callback is called // again with the name of the next advertised // service found.

bReturnValue = TRUE; }

else {

// Method received an empty buffer for service name, // returning false in this scenario will cause stop // receiving any more Service name i.e. this method // will not be called again.

} return bReturnValue;

}

// This method uses acsEnumServerNames() TSAPI method to specify// a callback method that will be called for each service name. void EnumerateServiceNames() {

// Enumerate the names of all servers of a specified stream type. RetCode_t nRetCode = acsEnumServerNames(ST_CSTA, // Enumerate CSTA services DisplayServerNames, // callback method defined above NULL // user defined variable, // value of this variable // will be passed to the callback method as // lParam parameter. Passing NULL here to keep // the example code simple. );

if ( nRetCode != ACSPOSITIVE_ACK ) {

// some error occurred while sending request. cout<<" Error Code: "<<nRetCode;

// handle error. }

}

Code Snippet 3: Enumerating Advertised Services

Page 11: Application Initialization using Avaya AE Services TSAPI ... · Application Initialization using Avaya AE Services TSAPI SDK for Windows A Devconnect Tutorial Table of Contents ...

avaya.com

11

2.2 OPENING A STREAM

The acsOpenStream() method is used for a request to open a stream with TSAPI Service. An application needs an

API Control Services (ACS) stream to access other API Control Services or CSTA Services. Thus, an application

must call acsOpenStream() before requesting any other ACS or CSTA service.

The acsOpenStream() method returns immediately with a return value indicating partial success or failure;

a confirmation event that confirms the success arrives later.

The acsOpenStream()method returns a handle (acsHandle) which references the opened ACS stream. The

application will use this acsHandle to access the ACS stream (to make requests and receive events).

When a stream is successfully opened, the application receives an ACSOpenStreamConfEvent event that corresponds

to the acsOpenStream() request. The application must wait for the ACSOpenStreamConfEvent event before requesting

any other ACS or CSTA service.

If the application needs to use extended features supported by a specific Private Data version then the

application can specify the Private Data version in the acsOpenStream()method call. In such case, when

the ACSOpenStreamConfEvent event is received, the application needs to validate that required Private Data

version is negotiated successfully. The application must use the same Private Data version returned in the

ACSOpenStreamConfEvent event and request only the features that are supported in the returned Private Data

version. To see the list of features supported in different Private Data versions, refer to Reference [1], Appendix B,

“Summary of Private data support”. For more information regarding Private Data version negotiation procedure, see

Section 5.1.

To match a service request with their corresponding confirmation/failure events, the application can use invokeID.

To know more about invokeID, see Appendix A: Notes, Note 1, “What is InvokeID?”

Note the following important points:

1. The application should always wait to receive the ACSOpenStreamConfEvent event before requesting any CSTA

Service requests.

2. The application is responsible for releasing its ACS stream(s). To release the system resources associated with

an opened (or active) ACS stream, the application may either close the stream or abort the stream. When the

application is designed to work with multiple streams, then it becomes even more important to release the

previously opened streams when they are not required (or not is use).

3. An acsHandle is a local process identifier and should not be shared across processes.

Page 12: Application Initialization using Avaya AE Services TSAPI ... · Application Initialization using Avaya AE Services TSAPI SDK for Windows A Devconnect Tutorial Table of Contents ...

avaya.com

12

2.2.1 acsOpenStream Method

acsOpenStream Method’s Signature:

RetCode_t acsOpenStream( ACSHandle_t *acsHandle, /* OUTPUT */ InvokeIDType_t invokeIDType, /* INPUT */ InvokeID_t invokeID, /* INPUT */ StreamType_t streamType, /* INPUT */ ServerID_t *serverID, /* INPUT */ LoginID_t *loginID, /* INPUT */ Passwd_t *passwd, /* INPUT */ AppName_t *applicationName, /* INPUT */ Level_t acsLevelReq /* INPUT */ Version_t *apiVer, /* INPUT */ unsigned short sendQSize, /* INPUT */ unsigned short sendExtraBufs, /* INPUT */ unsigned short recvQSize, /* INPUT */ unsigned short recvExtraBufs /* INPUT */ PrivateData_t *privateData); /* INPUT */

Code Snippet 4: acsOpenStream() Method’s Signature

Applications calling the acsOpenStream()method need to pass a set of parameters for setting up the environment

and performing a handshake between themselves and TSAPI Service. Each parameter of the acsOpenStream()

method is described below:

acsOpenStream Method’s Parameters:

• acsHandle: The acsOpenStream service request returns this value that identifies the ACS stream that was

opened. The TSAPI library sets this value so that it is unique to the ACS stream. Once acsOpenStream() is

successful, the application must use this acsHandle in all other method calls to TSAPI Service on this stream.

If acsOpenStream() is successful, the TSAPI library guarantees that the application has a valid acsHandle.

• invokeIDtype: The application sets the type of invoke identifiers used on the stream being opened. Two

possible values are APP_GEN_ID for Application-generated invokeIDs and LIB_GEN_ID for Library generated

invokeIDs. For more information on InvokeIDType, refer to Note 1 What is InvokeID.

• invokeID: The application supplies this handle for matching the acsOpenStream() service request with its

confirmation event. An application supplies a value for invokeID only when the invokeIDtype parameter is set

to APP_GEN_ID. TSAPI ignores the invokeID parameter when invokeIDtype parameter is set to LIB_GEN_ID.

For more information on InvokeID, refer to Note 1 What is InvokeID.

• streamType: The application provides the type of stream in streamType. The value of streamType when opening

ACS stream for CSTA services needs to be:

— ST_CSTA - identifies a request as a CSTA call control stream. This stream can be used for TSAPI Service

requests and responses which begin with the prefix “csta”.

• serverID: The application provides a null-terminated string of maximum size ACS_MAX_SERVICEID. This string

contains the name of an advertised service (in ASCII format). The application must ensure that the serverID

advertised service provides services of the type given in the streamType parameter. An application can use

Page 13: Application Initialization using Avaya AE Services TSAPI ... · Application Initialization using Avaya AE Services TSAPI SDK for Windows A Devconnect Tutorial Table of Contents ...

avaya.com

13

acsEnumServerNames()method to get the list of advertised services of the given type offered by the AE

Services server. Please refer to Section 2.1.2 for additional details.

• loginID: The application provides a pointer to a null terminated string of maximum size ACS_MAX_LOGINID. This string

contains the login ID of the CTI user requesting access to the advertised service given in the serverID parameter.

• passwd: The application provides a pointer to a null terminated string of maximum size ACS_MAX_PASSWORD.

This string contains the password of the CTI user given in loginID.

• applicationName: The application provides a pointer to a null terminated string of maximum size ACS_MAX_

APPNAME. This string contains an application name. The AE Services system uses the application name on

certain administration and maintenance status displays.

• acsLevelReq: This parameter is ignored.

• apiVer: The application uses this parameter to specify the TSAPI version it can work with. This parameter

contains a string beginning with the characters “TS” followed by an ASCII encoding of one or more version

numbers. An application may use the “-” (hyphen) character to specify a range of versions and the “:” (colon)

character to separate a list of versions. For example, the string “TS1-3:5” specifies that the application is

willing to accept TSAPI versions 1, 2, 3, or 5.

• sendQSize: The application specifies via sendQsize the maximum number of outgoing messages the TSAPI

Client library will queue before returning ACSERR_QUEUE_FULL. If the application supplies a zero (0) value,

then a default queue size will be used.

• sendExtraBufs: The application specifies the number of additional packet buffers that TSAPI needs to allocate

for the send queue. If sendExtraBufs is set to zero (0), the number of buffers is equal to the default queue

size (i.e., one buffer per message). If the user expects messages to exceed the size of a network packet

(which can happen if the application use Private Data extensively), they should allocate additional buffers

i.e., the application needs to increase the sendExtraBufs value. Also, if the application frequently receives the

error ACSERR_NOBUFFERS, it indicates that the application has not allocated enough buffers.

• recvQSize: The application specifies via recvQSize the maximum number of incoming messages the TSAPI

Client library queues before it ceases acknowledgment to AE Services server. TSAPI uses a default queue

size when recvQSize is set recvExtraBufs: The application specifies via recvExtraBufs the number of additional

packet buffers that TSAPI needs to allocate for the receive queue. If recvExtraBufs is set to zero (0), the

number of buffers is equal to the default queue size (i.e., one buffer per message). If the messages exceed

the size of a network packet, as is the case where Private Data is used extensively, or the application

frequently sees ACSERR_STREAM_FAILED, it indicates that the application has not allocated a large enough

buffer using recvExtraBufs i.e., the application needs to increase the size of recvExtraBufs.

• privateData: The application uses this parameter to provide a pointer to a data structure that contains any

implementation-specific initialization. For TSAPI Service, this pointer is used to specify Avaya Private Data.

The TSAPI protocol does not interpret the data in this structure. An application can pass version negotiation

information in the Private Data parameter of the acsOpenStream() method. An application that does not use

Page 14: Application Initialization using Avaya AE Services TSAPI ... · Application Initialization using Avaya AE Services TSAPI SDK for Windows A Devconnect Tutorial Table of Contents ...

avaya.com

14

Private Data should pass NULL in this parameter while calling the acsOpenStream() method. Refer to Chapter 5

for detailed information about Private Data and Private Data version negotiation.

acsOpenStream Method’s Return Values:

acsOpenStream() method’s return value follows the same convention as described in Note 2, Common Return Values.

The application should always check the ACSOpenStreamConfEvent message to ensure that TSAPI Service has

positively acknowledged the acsOpenStream() request.

acsOpenStream() returns the following negative error conditions:

• ACSERR_APIVERDENIED - The requested API version (apiVer) is invalid or the client library does not support it.

• ACSERR_BADPARAMETER - One or more of the parameters are invalid.

• ACSERR_NODRIVER - No TSAPI Client library driver was found or installed on the system.

• ACSERR_NOSERVER - The advertised service (serverID) is not available in the network. The application can also

receive this error when the application is trying to access a secured TLink. For more information, see Note 4,

Accessing a Secured TSAPI Link (Tlink).

• ACSERR_NORESOURCE - There are insufficient resources to open an ACS stream.

• ACSERR_SSL_INIT_FAILED - This return value indicates that a secure connection could not be opened because

there was a problem initializing the OpenSSL library.

• ACSERR_SSL_CONNECT_FAILED - This return value indicates that a stream could not be opened because there

was a problem establishing an SSL connection to the server. It may be that the server failed to provide a

certificate, or that the server certificate is not signed by a trusted Certificate Authority.

• ACSERR_SSL_FQDN_MISMATCH - This return value indicates that a stream could not be opened because the

FQDN (Fully Qualified Domain Name) in the server certificate does not match the expected FQDN.

• acsOpenStream() may also return ACSERR_STREAM_FAILED if the application attempts to open a stream to a secure

(encrypted) Tlink but the TSAPI Client library (release 4.0.x or earlier) does not support secure client connections.

Some failures are detected by the AE Services server and are thus not available immediately from the method’s

return value. The application must be prepared to receive any of the following events anytime after the

acsOpenStream() method completes:

• an ACSUniversalFailureConfEvent (when there is an error related to ACS Stream),

• CSTAUniversalFailureConfEvent (error while processing CSTA request), or

• ACSUniversalFailureEvent (when ACS stream is failed).

Page 15: Application Initialization using Avaya AE Services TSAPI ... · Application Initialization using Avaya AE Services TSAPI SDK for Windows A Devconnect Tutorial Table of Contents ...

avaya.com

15

These events contain the failure cause and also indicate that a failure has occurred on the stream. Some of the

failures that can be received in these events are tserverBadPasswordOrLogin, tserverNoUserRecord, etc. Please

refer to Appendix B: Complete Example Code to see how these events are handled in the Notify() method.

A TSAPI client application can also access a secured Tlink (or advertised service name or Server ID). For more

information, see Appendix A: Notes, Note 4, ”Accessing a Secured TSAPI Link (Tlink).”

acsOpenStream Code Example:

The following code snippet shows a call to the acsOpenStream() method. Refer to the OpenACSStream() method

in Appendix B: Complete Example Code for the complete procedure of calling the acsOpenStream() method.

// Open a stream with Private Data negotiation & with library// generated InvokeID. This method will returns invokeID on success // as LIB_GEN_ID is used. The invokeID will be stored in nRetCode.

// If the application does not wish to receive Private Data, it should // pass NULL in privateData parameter.

RetCode_t nRetCode = acsOpenStream(acsHandle, LIB_GEN_ID, // Library takes the control for generating InvokeID. 0, // This param is ignored when 2nd parameter is LIB_GEN_ID ST_CSTA, // requesting CSTA stream type. (ServerID_t*)"AVAYA#CMSIM#CSTA#AESSIM", // CTI Link name // AVAYA#SWITCH1#CSTA#SERVERNAME1" (LoginID_t*)"avaya", // CTI user login ID

(Passwd_t*)"Avayapassword", // CTI user password (AppName_t*)"DeviceMonitor", // name of the application ACS_LEVEL1, // LevelReq, This parameter will be ignored

(Version_t*) "TS1-2", // API Version 0,// send queue size using default 5, // send extra buf size 0, // receive queue size using default 10, // receive extra bufs (PrivateData_t *)&privateData // includes version negotiation information. // Refer to section 5.1 to see how to prepare // version negotiation information. );

Code Snippet 5: acsOpenStream() Code Example

2.3 CLOSING A STREAM

Similar to opening a stream, a client application also needs to close a stream. Once the client application finishes

its operations and is about to exit, it should close all the open stream(s) to free up the system resources consumed

by the opened stream(s).

The application uses the acsCloseStream()method to close an ACS stream. The application will be unable to

request services from TSAPI Service after the acsCloseStream() method has returned successfully.

Page 16: Application Initialization using Avaya AE Services TSAPI ... · Application Initialization using Avaya AE Services TSAPI SDK for Windows A Devconnect Tutorial Table of Contents ...

avaya.com

16

2.3.1 acsCloseStream Method

acsCloseStream Method’s Signature:

RetCode_t acsCloseStream ( ACSHandle_t acsHandle, /* INPUT */ InvokeID_t invokeID, /* INPUT */ PrivateData_t* privateData /* INPUT */ );

Code Snippet 6: acsCloseStream() Method’s Signature

acsCloseStream Method’s Parameters:

• acsHandle - This is the handle for the active ACS stream which is to be closed. Once the confirmation event

associated with this request is received, the handle is no longer valid.

• invokeID - A handle provided by the application, used for matching a confirmation event with this request. This

parameter is used only when the InvokeID mechanism is set for application-generated IDs in acsOpenStream( ) method.

This parameter is ignored by the TSAPI Client library when the stream is set for library-generated invoke IDs.

• privateData - This parameter is ignored. Hence, a NULL is required to be passed in this parameter for the

acsCloseStream() method.

acsCloseStream Method’s Return Values:

The acsCloseStream() method’s return value follows the same convention as described in Note 2, Common Return Values.

The possible negative error condition for acsCloseStream() method is:

• ACSERR_BADHDL - This indicates that the acsHandle being used is not a valid handle for an active ACS

stream. No changes occur in any existing streams if a bad handle is passed with this method.

When the acsCloseStream() method returns with a non-negative value, the application must wait to receive the

ACSCloseStreamConfEvent event to ensure that the service request has been processed successfully by AE Services

server and the ACS stream was properly closed. No new service requests will be accepted for the specified acsHandle

after this method successfully returns. However, the handle is still active and valid until the application receives the

ACSCloseStreamConfEvent i.e., the application will continue to receive pending events on this stream.

See Chapter 7: for information on handling the ACSCloseStreamConfEvent event.

acsCloseStream Example Code:

A sample code snippet for the acsCloseStream() method is given below. Refer to the CloseStream() method in

Appendix B: Complete Example Code for the complete procedure of calling the acsCloseStream() method.

// Request to close an ACS stream. A confirmation event will be provided for this// method. RetCode_t nRetCode = acsCloseStream(acsHandle, // Handle of the active ACS stream 0, // Using library generated invokeID, passing 0 NULL);, // Private data not used, passing NULL

Code Snippet 7: acsCloseStream() Code Example

Page 17: Application Initialization using Avaya AE Services TSAPI ... · Application Initialization using Avaya AE Services TSAPI SDK for Windows A Devconnect Tutorial Table of Contents ...

avaya.com

17

2.4 ABORTING A STREAM

This method unilaterally closes an ACS stream to TSAPI Service. The application will be unable to request services

from TSAPI Service or receive events after the acsAbortStream() method has returned. The acsHandle is invalid on

this stream after the acsAbortStream() method returns. There is no associated confirmation event for this method.

2.4.1 acsAbortStream Method

acsAbortStream Method’s Signature:

RetCode_t acsAbortStream( ACSHandle_t acsHandle, /* INPUT */ PrivateData_t* privateData /* INPUT */ );

Code Snippet 8: acsAbortStream() Method’s Signature

acsAbortStream Method’s Parameters:

• acsHandle - This is the handle for the active ACS stream which is to be aborted. Once acsAbortStream()

method returns successfully, the handle becomes invalid.

• privateData – This parameter is ignored. Hence, a NULL is required to be passed in this parameter for the

acsAbortStream() method.

acsAbortStream Method’s Return Values:

This method returns zero (0) if successful. The possible negative error condition for this method is:

• ACSERR_BADHDL - This indicates that the acsHandle being used is not a valid handle for an active ACS

stream. No changes occur in any existing streams if a bad handle is passed to this method.

acsAbortStream Example Code:

The following code snippet shows the procedure to invoke the acsAbortStream() method. Refer to the AbortStream()

method in Appendix B: Complete Example Code for the complete procedure of calling the acsAbortStream() method.

// Request to abort an ACS stream. There is no confirmation event for this// method. RetCode_t nRetCode = acsAbortStream(acsHandle, // Handle of the active ACS stream. NULL // Private data not used, passing NULL );

Code Snippet 9: acsAbortStream() Code Example

2.5 DIFFERENCES BETWEEN THE ACSCLOSESTREAM() AND ACSABORTSTREAM() METHODS

While both acsCloseStream() and acsAbortStream() serve a similar purpose, there are some differences between

them. A list of these differences is presented below:

1. In the case of the acsAbortStream(), the ACS stream’s handle becomes invalid immediately after the

acsAbortStream() returns, while in the case of acsCloseStream(), the Stream’s handle remains valid until the

application receives a corresponding confirmation event for acsCloseStream().

Page 18: Application Initialization using Avaya AE Services TSAPI ... · Application Initialization using Avaya AE Services TSAPI SDK for Windows A Devconnect Tutorial Table of Contents ...

avaya.com

18

2. In the case of acsCloseStream(), there is an associated confirmation event, while there is no associated

confirmation event for acsAbortStream().

3. In the case of the acsAbortStream(), the system frees all resources associated with the aborted ACS Stream

immediately, including any events queued on this stream, while in the case of acsCloseStream(), the application

will continue to receive events until it receives the confirmation event for the acsCloseStream() . Once the

confirmation event is received, the system will free all resources associated with the closed ACS Stream.

An application may use acsAbortStream() to unilaterally (and synchronously) terminate an ACS stream when:

• It does not require a confirmation of a successful stream closure, and,

• It does not need to receive any events that may be queued for it on that stream.

Section 3: Control Services and the Request/Response Model

This chapter describes in detail the control services provided by the TSAPI interface, supported event types and

the request and response framework.

3.1 CONTROL SERVICES

The TSAPI interface provides two types of controlling services:

• Application Programming Interface (API) Control Services (also referred to as ACS)

• CSTA control services

3.1.1 Application Programming Interface (API) Control Services

Applications use API Control Services (ACS) to manage the interactions with TSAPI Service running on the AE

Services server. These interactions primarily include services required for maintaining sessions and handling the

event queue maintained by the TSAPI Client library. The method names of the APIs providing these services start

with ‘acs‘, e.g., acsOpenStream() method.

Applications can use ACS functions to do the following:

• Get a list of available advertised services.

• Open an ACS stream with (or without) Private Data version negotiation.

• Close an ACS stream.

• Block or poll for events.

• Query an ACS stream for its service name (beginning with AE Services 4.1).

• Control the interval at which TSAPI Service sends heartbeat events to the client (beginning with AE Services 4.1).

Page 19: Application Initialization using Avaya AE Services TSAPI ... · Application Initialization using Avaya AE Services TSAPI SDK for Windows A Devconnect Tutorial Table of Contents ...

avaya.com

19

3.1.2 CSTA Control Services

CSTA control services provide CSTA functionality for the TSAPI interface. These services are as defined in the

CSTA specifications and start with ‘csta’, as in the cstaMonitorDevice() method. Applications can use these services

only after opening an ACS stream.

The following services are available via CSTA control services:

• Call Control Services.

• Escape Services.

• Maintenance Services.

• Query Services.

• Routing Services.

• Set Feature Services.

• Snapshot Services.

• Status Services.

3.2 REQUEST/RESPONSE MODEL

Avaya’s TSAPI implementation of CSTA services follows a multi-step request and response model, and therefore

each CSTA service request results in an event sent back to the application asynchronously.

An application sends a request (or TSAPI requests), requesting TSAPI Service to take some action. The AE

Services server then processes each request. The server may take additional steps to pass the request to

Communication Manager and handle the response(s) before responding asynchronously to the application.

Synchronous response in the form of return code for the request merely indicates that the request was received

and is being processed. The actual request’s result is communicated back to the application in the form a

confirmation event later.

3.2.1 TSAPI Requests

After successfully opening an ACS stream, an application may request different CSTA services by sending TSAPI

requests. In each service request, the application passes the handle of the stream over which it is making the

request. Each service request passes an invokeID to distinguish it from the other service requests. The invokeID

provides a way to match the confirmation/failure event to the corresponding service request. An invokeID used by

the application must be unique so that the application can associate the response with the appropriate request.

3.2.2 TSAPI Responses

TSAPI Service sends a response to every request. This could be a positive acknowledgement in case of success

or a negative response in case of a failure. A TSAPI response is also referred to as the confirmation event sent by

TSAPI Service. See Chapter 4: for detailed information regarding event handling.

As an example, the cstaMakeCall() method is used here to illustrate the request/response model (Figure

3). When an application sends a request to make a call using the cstaMakeCall() method, it receives a

Page 20: Application Initialization using Avaya AE Services TSAPI ... · Application Initialization using Avaya AE Services TSAPI SDK for Windows A Devconnect Tutorial Table of Contents ...

avaya.com

20

CSTAMakeCallConfEvent confirmation event as a response to the service request. In this example, the application is

using a library generated invokeID, and therefore the client library is responsible for generating a unique numeric

identifier (e.g., 123), representing invokeID, and return to the application.

Figure 3: TSAPI Application Request/Response

Section 4: Event Handling

This chapter explains the reader how TSAPI Service responds to requests sent by the TSAPI application using

client library. This chapter also describes the types of events supported, different ways to register the event handler

with the TSAPI Client library, and how to extract the event information from the event object.

Once the acsOpenStream() method returns successfully, the application should set up the event notification to

receive events and confirmation responses before requesting any other services. A TSAPI application typically

performs the following steps:

• Event Handler Registration: Setup the notification mechanism for receiving a notification when an event is

added in the TSAPI Client’s receive queue.

• Events Enablement: Start monitors to receive events for status changes.

• Retrieve Events: Retrieve events from the TSAPI Client’s receive queue using either acsGetEventBlock() or

acsGetEventPoll() method.

• Event Information Retrieval: Extract event information (including Private Data) from the received events.

Page 21: Application Initialization using Avaya AE Services TSAPI ... · Application Initialization using Avaya AE Services TSAPI SDK for Windows A Devconnect Tutorial Table of Contents ...

avaya.com

21

4.1 TYPES OF EVENTS

In Avaya TSAPI, there are two types of event messages that are sent by AE Services server to the application:

1. UNSOLICITED events.

2. CONFIRMATION events.

A TSAPI application receives UNSOLICITED events in the form of ACSUNSOLICITED/CSTAUNSOLICITED events and

CONFIRMATION events in the form of ACSCONFIRMATION/CSTACONFIRMATION events.

1. UNSOLICITED events: UNSOLICITED events report state changes of various objects, such as call or device objects,

managed by Communication Manager. In addition to setting up a notification mechanism, applications need

to start a monitor on the desired object. Once the monitor is established, any changes to the object’s state are

reported to the monitoring application through these events.

Multiple unsolicited events could be received for a single monitor. For example, after a call monitor is started

by the application, events such as CSTA_ESTABLISHED, CSTA_HELD are sent to the application when the call state

changes.

2. CONFIRMATION events: A CONFIRMATION event is received as a response to a TSAPI request. There is only one

confirmation event sent for each TSAPI request. The application needs to setup the notification mechanism for

receiving these events. For example, TSAPI Service will send a CSTAMonitorConfEvent event to an application

after TSAPI Service has successfully processed the cstaMonitorDevice request.

The application must handle these events by setting up the appropriate notification mechanisms.

4.2 SETTING UP THE NOTIFICATION MECHANISM

The application should set up the notification mechanism to get notified about incoming events. There are

two mechanisms by which the application can be notified about the events: the Event Service Routine (ESR)

mechanism, and the acsEventNotify() method. In both approaches, the application is notified about the arrival of

a new event in the queue. Functions described in the next two sections do not remove the events from the event

queue. It is the application’s responsibility to retrieve the event from the event queue. Section 4.4 provides more

information on retrieving events.

4.2.1 The Event Service Routine (ESR) Mechanism

The application can use the ESR (Event Service Routine) mechanism to receive an asynchronous notification

of the arrival of an incoming event from TSAPI Service. The acsSetESR() method enables the notification of

incoming events via an application-defined callback method. This callback method will be invoked whenever

there is an event added in the TSAPI Client library queue. A pointer to the callback method is passed through

the esr parameter of thThe acsSetESR() method should be invoked once the acsOpenStream() method is returned

successfully before requesting any other services. Whenever the callback method is called, the application must

retrieve the events from the Client library’s event queue to prevent the queue from overflowing.

Page 22: Application Initialization using Avaya AE Services TSAPI ... · Application Initialization using Avaya AE Services TSAPI SDK for Windows A Devconnect Tutorial Table of Contents ...

avaya.com

22

It is recommended that the application should be designed to have a separate thread (one different from the

callback method thread) for retrieving and processing the events. In cases where the application chooses to

receive a notification for each event whenever an event is added in the Client library’s event queue, the need to

retrieve and process the events in a separate thread becomes more evident. Retrieving and processing the events

in a separate thread ensures that the callback method’s thread is not blocked and remains free to receive further

notifications from the Client library.

4.2.1.1 acsSetESR Method

acsSetESR Method’s Signature:

typedef void (*EsrFunc)(unsigned long esrParam);

RetCode_t acsSetESR (ACSHandle_t acsHandle, /* INPUT */ EsrFunc esr, /* INPUT */ unsigned long esrParam, /* INPUT */ Boolean notifyAll /* INPUT */ );

Code Snippet 10: acsSetESR() Method’s Signature

acsSetESR Method’s Parameters:

• acsHandle - This is the value of the unique handle to the opened stream, for which this ESR routine will

apply. Only one ESR is allowed per active acsHandle.

• esr - This is a pointer to the ESR (the address of a method). The application can pass a NULL pointer to clear

an existing ESR.

• esrParam - This is a user-defined parameter which will be passed to the ESR when it is called.

• notifyAll - If this parameter is TRUE then the ESR will be called for every event. If it is FALSE then the ESR will

only be called each time the receiving queue becomes non-empty, i.e., the queue count changes from zero

(0) to one (1). This option may be used to reduce the overhead of notification.

acsSetESR Method’s Return Values:

A positive return value indicates success and a negative return value indicates failure. There is no confirmation

event for this method. The positive return value is:

• ACSPOSITIVE_ACK: The method completed successfully as requested by the application. No errors were detected.

Possible error is (negative return value):

• ACSERR_BADHDL: This indicates that the acsHandle being used is not a valid handle for an active ACS stream.

No changes occur in any existing streams if a bad handle is passed with this method.

acsSetESR Example Code:

The following code snippet shows a call to the acsSetESR() method. Refer to the OpenACSStream() and

ESRCallback() methods in Appendix B: Complete Example Code to see the complete procedure of calling the

acsSetESR() method, as well as how an application can implement the callback method.

Page 23: Application Initialization using Avaya AE Services TSAPI ... · Application Initialization using Avaya AE Services TSAPI SDK for Windows A Devconnect Tutorial Table of Contents ...

avaya.com

23

// Register a callback method with client library to receive a notification when an// event is available in the Client library’s event queue. // Upon success, the Client library will call ESRCallback method whenever there is// an event available in its event queue.

nRetCode = acsSetESR(acsHandle, // handle returned by the acsOpenStream() method ESRCallback, // callback method defined by the application (unsigned long)acsHandle, // passing the ACS stream handle as // user defined parameter TRUE); // Setting TRUE to receive callback for each event added to // the client library’s event queue.

// check the return code if(nRetCode != ACSPOSITIVE_ACK) { cout<<" ERROR: acsSetESR() method return with an error.";

if(nRetCode == ACSERR_BADHDL) { cout<<" ulAcsHandle being used is not a valid handle"<<endl; }

else { cout << " acsSetESR() failed with unknown error. " << endl; cout << " Error code: " << nRetCode; } }

Code Snippet 11: acsSetESR() Code Example

4.2.2 The acsEventNotify() Method

The acsEventNotify() method is used to enable the notification for an incoming event via Windows messages.

This method allows an application to request that an application defined message be posted to the application’s

message queue when an incoming ACS or CSTA event is available. Once the application invokes this method with

the appropriate values, TSAPI Service starts sending the application defined message to the application’s message

queue with the appropriate event class and event type information. The acsEventNotify() method should be invoked

once the acsOpenStream() method is returned successfully before requesting any other services.

4.2.2.1 acsEventNotify Method

acsEventNotify Method’s Signature:

RetCode_t acsEventNotify (ACSHandle_t acsHandle, /* INPUT */ HWND hwnd, /* INPUT */ UINT msg, /* INPUT */ Boolean notifyAll /* INPUT */ );

Code Snippet 12: acsEventNotify() Method’s Signature

acsEventNotify Method’s Parameters:

• acsHandle - This is the value of the unique handle to the opened ACS stream for which event notification

messages will be posted.

Page 24: Application Initialization using Avaya AE Services TSAPI ... · Application Initialization using Avaya AE Services TSAPI SDK for Windows A Devconnect Tutorial Table of Contents ...

avaya.com

24

• hwnd - This is the handle of the window which is to receive event notification messages. If this parameter is

NULL, event notification is disabled.

• msg - This is the user-defined message to be posted when an incoming event becomes available. The wParam and

lParam parameters of the message will contain information about the event class and event type respectively.

• notifyAll - If this parameter is TRUE then a message will be posted for every event. If it is FALSE then a

message will only be posted each time the receive queue becomes non-empty.

acsEventNotify Method’s Return Values:

A positive return value indicates success and a negative return value indicates failure. There is no confirmation

event for this method. The positive return value is:

• ACSPOSITIVE_ACK: The method completed successfully as requested by the application. No errors were detected.

Possible error is (negative return value):

• ACSERR_BADHDL: This indicates that the acsHandle provided is not a valid handle for an active ACS stream.

No changes occur in any existing streams if a bad handle is passed with this method.

Page 25: Application Initialization using Avaya AE Services TSAPI ... · Application Initialization using Avaya AE Services TSAPI SDK for Windows A Devconnect Tutorial Table of Contents ...

avaya.com

25

acsEventNotify Example Code:

// A message identifier can be defined like this. #define WM_ACSEVENT WM_USER + 101 // Method to open an ACS stream bool OpenACSStream(ACSHandle_t acsHandle);

// <summary> // This method creates a window and display it. After window is displayed, this // method calls internal method to open an ACS stream. If the stream is // opened successfully, this method calls acsEventNotify() TSAPI method to register// for receiving a notification when when an incoming ACS event is available. // </summary>

BOOL InitInstance(HINSTANCE hInstance, int nCmdShow) { HWND hWnd; // Set the handle of the window

// Create the main window. hWnd = CreateWindow( L"MainWClass", // name of window class L"Sample", // title-bar string WS_OVERLAPPEDWINDOW, // top-level window CW_USEDEFAULT, // default horizontal position CW_USEDEFAULT, // default vertical position CW_USEDEFAULT, // default width CW_USEDEFAULT, // default height (HWND) NULL, // no owner window (HMENU) NULL, // use class menu hInstance, // handle to application instance (LPVOID) NULL); // no window-creation data

if (!hWnd) {

// creation of new window failed return FALSE;

}

ShowWindow(hWnd, nCmdShow); UpdateWindow(hWnd);

// Once the Window is displayed, the application send a request for // opening the ACS Stream.

// Handle to ACS stream ACSHandle_t acsHandle;

// OpenACSStream method is an user-defined method that send a request to// open a ACS stream. It returns true when ACS Stream is opened successfully. // See example code for implementation of OpenACSStream()method. if( OpenACSStream(acsHandle) )

{ RetCode_t nRetCode; // To store the return code

nRetCode = acsEventNotify((ACSHandle_t)acsHandle, // Handle of // active ACS Stream hWnd, // window handle WM_ACSEVENT, // Message ID in winproc TRUE // TRUE will enable the message to be // posted for every event. );

// Verification for the positive response if(nRetCode != ACSPOSITIVE_ACK)

Page 26: Application Initialization using Avaya AE Services TSAPI ... · Application Initialization using Avaya AE Services TSAPI SDK for Windows A Devconnect Tutorial Table of Contents ...

avaya.com

26

{ // ERROR in acsEventNotify if(nRetCode == ACSERR_BADHDL)

{ // acsHandle being used is not a valid handle.

} else

{ // acsEventNotify() failed with unknown error. // Error code: nRetCode

} return FALSE;

} else

{ // acsEventNotify call is successful.

} }

else {

// Error: Open Stream request failed. }

return TRUE; }

// Application’s Windows procedure that will be called whenever there is a// new message posted for any of the windows belonging to this application. LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {

// wParam contains an ACSHandle_t // HIWORD(lParam) contains an EventClass_t

EventClass_t eventClass = HIWORD(lParam); // LOWORD(lParam) contains an EventType_t

EventType_t eventType = LOWORD(lParam);

switch (message) {

case WM_CREATE: // other initialization, etc... break;

case WM_ACSEVENT: {

// User defined message; this message only indicates an incoming event is// available. Use acsGetEventBlock()/acsGetEventPoll( ) to actually // retrieve the complete event. // See Notify method for details on how can an application call

// acsGetEventBlock()/acsGetEventPoll() to retrieve an event from the // client queue.

cout << "Event class received is : " << eventClass; cout << "Event type received is : " << eventType; }

default: {

// Unhandled message received } } // End of switch

}// End of Method

Code Snippet 13: acsEventNotify() Code Example

The acsEventNotify() method enables a notification to be sent for an incoming event; extracting events from the

Client library’s event queue is the responsibility of the application. To do this, the application can use either

the acsGetEventBlock()or the acsGetEventPoll() method. Refer to Section 7.5 for an example of how to use the

acsGetEventBlock() and acsGetEventPoll() methods.

Page 27: Application Initialization using Avaya AE Services TSAPI ... · Application Initialization using Avaya AE Services TSAPI SDK for Windows A Devconnect Tutorial Table of Contents ...

avaya.com

27

4.3 STARTING MONITORS FOR UNSOLICITED EVENTS

To receive unsolicited events, the application first needs to start a monitor on objects such as a call or a device. The term device

refers to both physical devices (stations, trunks, and so on) and logical devices (VDNs or ACD splits), that are controlled by

Avaya Communication Manager. Each device is characterized by a set of attributes. These attributes define the manner in which

an application may observe and manipulate a device. For more information, see Reference [1], Chapter 4 “CSTA Objects”.

When there is a change in the status of a monitored object, the application receives an unsolicited event. The

Avaya TSAPI Client API provides different methods which can be used to set monitors.

A TSAPI application can use the cstaMonitorCall() method to monitor a call, and cstaMonitorDevice() to monitor a

device. For more information on monitoring services, see Reference [1], Chapter 10.

The Code Snippet 14 shows the usage of the cstaMonitorDevice() method.

// MonitorDevice() : This method demonstrates the use of cstaMonitorDevice()// method which is used to monitor the device (Extension) // and to receive the events that arrive for the device after// monitor request acknowledged. void MonitorDevice(ACSHandle_t acsHandle) { DeviceID_t szDeviceID = "40011"; // device to be monitored

// Store the return code of the method RetCode_t nRetCode = 0;

CSTAMonitorFilter_t filter; // Store the Montor Filter setting

// Setting each fiter to 0 to receive all the events. filter.call = 0; filter.agent = 0; filter.feature = 0; filter.maintenance = 0; filter.privateFilter = 0;

nRetCode = cstaMonitorDevice(acsHandle, // ACS Stream handle 0, // Invoke ID is ignored, as it is library generated. &szDeviceID, // ID of the device to be monitored &filter, // Filter setting that will apply on monitor. NULL // Private data not passed with this request );

if(nRetCode < 0) { cout<<" Failed to monitor device ID: "<< szDeviceID <<endl; cout<<" Error code: " << nRetCode; }

else {

// cstaMonitorDevice returned successfully // InvokeID generated for this method will be returned in nRetCode, // applications can store this invokeID in any data structure for later// comparison. // See Complete Example Code to see saving and comparing invokeID.

}

}// End of method.

Code Snippet 14: cstaMonitorDevice() Code Example

Page 28: Application Initialization using Avaya AE Services TSAPI ... · Application Initialization using Avaya AE Services TSAPI SDK for Windows A Devconnect Tutorial Table of Contents ...

avaya.com

28

A confirmation event (i.e. CSTAMonitorConfEvent) is provided for each monitoring request. The CSTAMonitorConfEvent

event provides a monitor cross reference ID that the application can use to correlate the subsequent event reports

to the monitor request. Refer to Chapter 7: for an example of how to handle the CSTAMonitorConfEvent event.

4.4 RETRIEVING EVENTS

The TSAPI Client library stores all the events received from the TSAPI Service in a separate queue. To retrieve

these events from the Client library queue, the application must use one of the two event retrieval methods

provided by Avaya’s TSAPI implementation: blocking mode or non-blocking mode.

4.4.1 Blocking Mode

An application can use acsGetEventBlock()method to retrieve an event in blocking mode. In the blocking mode, the

application’s calling thread will be blocked until there is an event for the ACS stream that matches the acsHandle.

If acsHandle is set to zero, the application’s calling thread will block until there is an event for any ACS stream

opened by the application.

4.4.1.1 acsGetEventBlock Method

acsGetEventBlock Method’s Signature:

RetCode_t acsGetEventBlock ( ACSHandle_t acsHandle, /* INPUT */ void* eventBuf, /* OUTPUT */ unsigned short* eventBufSize, /* INPUT/OUTPUT */ PrivateData_t* privateData, /* OUTPUT */ unsigned short* numEvents /* OUTPUT */ );

Code Snippet 15: acsGetEventBlock() Method’s Signature

acsGetEventBlock Method’s Parameters:

• acsHandle - This is the value of the unique handle to the opened ACS stream. If a handle of zero (0) is given,

then the next message on any of the open ACS streams for this application is returned.

• eventBuf - This is a pointer to an area in the application address space large enough to hold one incoming

event. This buffer should be large enough to hold the largest event the application expects to receive.

Typically the application will reserve a space large enough to hold a CSTAEvent_t.

• eventBufSize - This parameter indicates the size of the user buffer pointed to by eventBuf. If the event is

larger than eventBuf, then this parameter will be returned with the size of the buffer required to receive the

event. The application should allocate a larger buffer and call the acsGetEventBlock() method again with a

pointer to the larger buffer.

• privateData - This parameter points to a buffer which will receive any Private Data that accompanies this

event. The length field of the PrivateData_t structure must be set to the size of the data buffer. If the

application does not wish to receive Private Data, then a NULL privateData pointer should be passed.

Page 29: Application Initialization using Avaya AE Services TSAPI ... · Application Initialization using Avaya AE Services TSAPI SDK for Windows A Devconnect Tutorial Table of Contents ...

avaya.com

29

• numEvents - The library will return the number of events queued for the application on the ACS stream whose

handle is passed in the acsHandle parameter (not including the current event) via the numEvents parameter. In the

case when there are more than one streams opened by the application, and acsGetEventBlock() method is called to

get an event from any of the opened streams by setting the first parameter (i.e. acsHandle) to zero (0), the value of

numEvents will reflect the number of events remaining on the stream from which the event was actually received.

When the TSAPI Client library receives the acsGetEventBlock()call, it will copy the event from its event queue

into the eventBuf parameter. The eventBuf parameter specifies the buffer to store the incoming CSTA or ACS

event. The buffer should be large enough to hold the largest event the application expects to receive.

The application can specify the size of the event buffer by using the eventBufSize parameter of this method.

Typically, the application will reserve a space large enough to hold a CSTAEvent_t event. This method returns

ACSPOSITIVE_ACK if the method completed successfully and the event copied to the application’s data space.

acsGetEventBlock Method’s Return Values:

A positive return value indicates success and a negative return value indicates failure. There is no confirmation

event for this method. The positive return value is:

• ACSPOSITIVE_ACK: The method completed successfully as requested by the application, and an event has

been copied to the application data space. No errors were detected.

Possible errors are (negative return value):

• ACSERR_BADHDL: This indicates that the acsHandle being used is not a valid handle for an active ACS stream.

No changes occur in any existing streams if a bad handle is passed with this method.

• ACSERR_UBUFSMALL: The user buffer size indicated in the eventBufSize parameter was smaller than the

size of the next available event for the application on the ACS stream. The application should call the

acsGetEventBlock() method again with a larger buffer to retrieve the event that is still present in the Client

Library queue.

acsGetEventBlock Example Code:

Refer to Code Snippet 17 for usage of the acsGetEventBlock() method.

4.4.2 Non-Blocking Mode

An application can use acsGetEventPoll() method to receive an event in non-blocking mode. In the non-blocking

mode, the oldest outstanding event for the specified active ACS stream or for any active ACS stream (in case

acsHandle is set to 0), will be copied into the application’s data space and control will be returned to the

application. If no events are currently queued for the application, the method will return control immediately to the

application with a return code indicating that no events were available.

The incoming event received by the application is passed by using the eventBuf parameter of the acsGetEventPoll()

method. This parameter specifies the buffer to hold the incoming event (CSTA or ACS).

Page 30: Application Initialization using Avaya AE Services TSAPI ... · Application Initialization using Avaya AE Services TSAPI SDK for Windows A Devconnect Tutorial Table of Contents ...

avaya.com

30

The buffer should be large enough to hold the largest event the application expects to receive. The application can

specify the size of the event buffer by using the eventBufSize parameter of this method. Typically the application

will reserve a space large enough to hold a CSTAEvent_t event.

4.4.2.1 acsGetEventPoll Method’s Signature:

acsGetEventPoll Method’s Signature:

RetCode_t acsGetEventPoll ( ACSHandle_t acsHandle, /* INPUT */ void* eventBuf, /* OUTPUT */ unsigned short* eventBufSize, /* INPUT/OUTPUT */ PrivateData_t* privateData, /* OUTPUT */ unsigned short* numEvents /* OUTPUT */ )

Code Snippet 16: acsGetEventPoll() Method’s Signature

acsGetEventPoll Method’s Parameters:

The acsGetEventPoll() method’s parameter are same as acsGetEventBlock() method. Refer to Section 4.4.1 for

detailed description of the parameters.

acsGetEventPoll Method’s Return Values:

The acsGetEventPoll()method return values are also same as return value of acsGetEventBlock() method (see

Section 4.4.1), with one exception:

• ACSERR_NOMESSAGE: There were no events available to return to the application.

acsGetEventPoll Example Code:

The following code snippet shows a call to the acsGetEventBlock() and acsGetEventPoll() methods. Refer

to the Notify() method in Appendix B: Complete Example Code for the complete procedure of calling the

acsGetEventBlock() and acsGetEventPoll() methods. See Chapter 7: to see event handling for other event handling

for other events.

Page 31: Application Initialization using Avaya AE Services TSAPI ... · Application Initialization using Avaya AE Services TSAPI SDK for Windows A Devconnect Tutorial Table of Contents ...

avaya.com

31

// BLOCKING_MODE can be defined in the project settings > C/C++ > // Preprocessor to use acsGetEventBlock() method. If application // wants to use acsGetEventPoll method instead, exclude BLOCKING_MODE // from project setting.

#ifdef BLOCKING_MODE { // Retrieving the events in Blocking mode // If no events are currently queued for the applcation then this method // will wait blocking the application's calling thread until an event // becomes available.

RetCode_t nRetCode = acsGetEventBlock(acsHandle, // Handle of active ACS // Stream. (void *)cstaEvent, // Event buffer &usEventBufSize, // size of event buffer (PrivateData_t *)&privateData, // private Data. &usNumEvents // count of events pending in queue );

} #else { // Retrieving events in Non-Blocking mode // If no events are currently queued for the application, this method // will return immediately with an error code ACSERR_NOMESSAGE // indicating that no events were available. RetCode_t nRetCode = acsGetEventPoll(acsHandle, (void *)cstaEvent, &usEventBufSize, (PrivateData_t *)&privateData, &usNumEvents); } #endif

if(nRetCode != ACSPOSITIVE_ACK) {

if(nRetCode == ACSERR_BADHDL) { cout<<" The ACS Handle is invalid"<<endl<<endl; } // end of if

else if (nRetCode == ACSERR_UBUFSMALL) { cout<<" Passed event buffer size is smaller than the size of the"

" next available event for this ACS Stream."<<endl<<endl;

// The usEventBufSize variable has been reset by the TSAPI Client// Library to the size of the next message on the ACS// stream. The application should call acsGetEventBlock( )// again with a larger buffer. The ACS event still present// on the Client Library queue.

Page 32: Application Initialization using Avaya AE Services TSAPI ... · Application Initialization using Avaya AE Services TSAPI SDK for Windows A Devconnect Tutorial Table of Contents ...

avaya.com

32

}// end of else if else if (nRetCode == ACSERR_NOMESSAGE)

{ // The acsGetEventPoll()method return this value to indicate // there were no events available in the Client library queue.

cout << " No events available at this time."; }

else { cout << " acsGetEventBlock()/acsGetEventPoll() failed with"

" unknown error. " << endl; cout << " Error code: " << nRetCode;

break; } }// end of if

else {

// We have successfully retrieved event, write event processing code here.}

Code Snippet 17: acsGetEventBlock() and acsGetEventPoll() Code Example

4.5 EXTRACTING EVENT INFORMATION

After receiving an event, the application should first check the event class and event type. The events received

from AE Services server are classified as either CSTACONFIRMATION/ACSCONFIRMATION (CONFIRMATION events) or

CSTAUNSOLICITED/ACSUNSOLICITED (UNSOLCITIED events).

Depending upon the event class and event type, the application should use appropriate event data structures to extract related

information. For example, when an application receives the DELIVERED event for a monitored object, the event class would be

CSTAUNSOLICITED and event type would be CSTA_DELIVERED. In this case, the application needs to use the CSTADeliveredEvent_t

event structure to extract information such as alerting device, calling device, etc. as shown in Code Snippet 18.

Page 33: Application Initialization using Avaya AE Services TSAPI ... · Application Initialization using Avaya AE Services TSAPI SDK for Windows A Devconnect Tutorial Table of Contents ...

avaya.com

33

void EventHanlder(CSTAEvent_t* cstaEvent) {

switch(cstaEvent->eventHeader.eventClass) {

case CSTAUNSOLICITED: {

switch(cstaEvent->eventHeader.eventType) {

case CSTA_DELIVERED: {

// Extract information included in this event here // Copy the Delivered Event.

CSTADeliveredEvent_t deliveredEvent = cstaEvent->event.cstaUnsolicited.u.delivered;

// Extract calling device char* callingDevice = deliveredEvent.callingDevice.deviceID;

cout << endl << " A Delivered event is received For device " << callingDevice << endl;

break; } // End of Case

// Add cases to handle other unsolicited events as per the application needs.

default: {

// Other application should add more cases as per need. cout << " An unhandled unsolicited event received."; cout<<" Event Type: "<< cstaEvent->eventHeader.eventType; } } // End of switch

break; } // End of Case

case ACSCONFIRMATION: {

// Extract information included in this event here break;

} // End of Case default:

{ cout << " Received event with unknown event class."; cout<<" Event Class: "<< cstaEvent->eventHeader.eventClass; } }// End of eventClass switch

}// End of method

Code Snippet 18: Extracting Event Information Code Example

Note:

Code Snippet 18: Extracting Event Information Code Example

Note: Code Snippet 18 shows how to retrieve information from the passed event object. For some events, there may

be some Private Data associated with the event. Section 5.3 describes how to extract the Private Data parameter

from an event. Refer the Notify() method in Appendix B: Complete Example Code for code to handle other

applicable cases.

Section 5: Private Data

This chapter provides detailed information about the Private Data parameter. Private Data is the means for both

extending the functionality of any defined CSTA service and for providing additional functionality altogether.

Page 34: Application Initialization using Avaya AE Services TSAPI ... · Application Initialization using Avaya AE Services TSAPI SDK for Windows A Devconnect Tutorial Table of Contents ...

avaya.com

34

TSAPI Service uses the “Private Data” mechanism to provide applications with access to special features of Avaya

Communication Manager.

Private Data may be defined for each CSTA service request, CSTA confirmation event, and CSTA unsolicited event.

Private Data allows a PBX or switch manufacturer to extend the base set of TSAPI capabilities. Over time, a PBX

manufacturer may choose to further enhance the capabilities that are available using Private Data.

A Private Data version defines a fixed set of features that are supported in the version. More specifically, it defines

a set of escape services and private event parameters for CSTA events. This lets the application developer know

exactly which services and Private Data items are available in a specific version. Having the ability to negotiate a

specific Private Data version ensures that an application written for an earlier release of AE Services will continue

to operate with newer releases.

To see the list of features supported in different Private Data versions, see Reference [1], Appendix B, “Summary

of Private data support”.

5.1 PRIVATE DATA NEGOTIATION

Any client application can use Private Data to access special features of Avaya Communication Manager. A special

feature means a set of information to achieve certain functionality, such as “Single Step Transfer Call”, “Calling

Device in Failed Event”, “Network Call Redirection for Routing” etc.

A PBX or switch manufacturer can add new functionality that can be accessed using Private Data; when they do

so, the Private Data version is set to a higher one than the previous version. To be able to use any special feature,

the application needs to know the Private Data version that contains that special feature. A particular Private Data

version is backward compatible with a previous one, i.e., it supports the entire set of features supported by an

earlier version.

To access any special features, the application needs to negotiate the correct Private Data version with TSAPI

Service. This is done at the time of opening an ACS stream. After the negotiation, the Private Data version remains

the same for all the requests and responses for this stream.

To negotiate Private Data Version (PDV), the acsOpenStream() method must be called with the privateData parameter

which is of type ATTPrivateData_t structure. This structure must contain the correctly formatted information to

negotiate PDV with which the application is compatible. An application that does not use Private Data should pass

NULL in privateData parameter at the time of calling the acsOpenStream() method.

The following data must be passed as the negotiation information in the privateData parameter in the

acsOpenStream() method:

• vendor: To indicate that Private Data negotiation is intended, the application sets the vendor field in the

PrivateData structure to the null terminated string “VERSION”.

• data: The application specifies the acceptable version(s) in the data field of ATTPrivateData_t structure. The

data field contains a constant PRIVATE_DATA_ENCODING followed by the null terminated ACSII string containing

the version or range of versions. The version string should be passed as formatted. The AE Services TSAPI

Page 35: Application Initialization using Avaya AE Services TSAPI ... · Application Initialization using Avaya AE Services TSAPI SDK for Windows A Devconnect Tutorial Table of Contents ...

avaya.com

35

SDK provides the attMakeVersionString() method to simplify formatting of the requested version string. The

application is required to format the version string using the attMakeVersionString() method.

• length: The length parameter of ATTPrivateData_t structure needs to be set appropriately to the total length of the

private data structure.

Note 5, Private Data Version Negotiation provides more information on the PDV negotiation process.

Code Snippet 19: Passing Private Data Negotiation Information Code Example illustrates the process to prepare

Private Data negotiation information to be sent in acsOpenStream() method. Refer to the OpenACSStream() method

in Appendix B: Complete Example Code for the complete procedure of preparing and sending Private Data

negotiation information in acsOpenStream() method.

// Below code demonstrate the process to send private data version// negotiation information in the acsOpenStream() method.// The application first set the vendor field of private data buffer // to VERSION and then prepare a ASCII string identifying the version // of the private data that the application wish to work with.

// ATT service request private data buffer ATTPrivateData_t privateData;

// privateData.vendor: should be set to 'VERSION' as follows strcpy_s(privateData.vendor, "VERSION");

// privateData.data: should be set to a one byte discriminator// PRIVATE_DATA_ENCODING followed by an ASCII string identifying// the version of the private dataprivateData.data[0] = PRIVATE_DATA_ENCODING;

Page 36: Application Initialization using Avaya AE Services TSAPI ... · Application Initialization using Avaya AE Services TSAPI SDK for Windows A Devconnect Tutorial Table of Contents ...

avaya.com

36

// A special function is used to convert version string into the format// required by the acsOpenStream function.

// Contain private data version that is requested by user // for negotiation.Version_t szPrivateDataVersion;

cout << endl << " Please enter private data version: ";cin >> szPrivateDataVersion;

if((attMakeVersionString(szPrivateDataVersion, &(privateData.data[1]))) > 0 ) {

// Adding 2 extra bytes here, one byte for element at zero location// (i.e. data[0] as it is one byte long) // and one byte for trailing null (as the ASCII string will be// null terminated).

// Set the privateData length privateData.length = (unsigned short) strlen(&privateData.data[1]) + 2;}else{

// attMakeVersionString failed due to incorrect version passed. cout << endl << "attMakeVersionString() method failed..."; cout << endl << "If you want to continue, a default Private Data"

" Version string (3-8) will be used." " Press y/Y to continue or any other key to exit the "

" application... ";char cContinue = _getche();

if(cContinue == 'Y' || cContinue == 'y') {

// As this application make use of private data, setting PDV to a// default value "3-8" in this case.

strcpy_s(szPrivateDataVersion, "3-8");

// Calling attMakeVersionString again with default PDV if ( (attMakeVersionString(szPrivateDataVersion, &(privateData.data[1])))

> 0 ) {

// Adding 2 extra bytes here, one byte for element at zero location// (i.e. data[0] as it is one byte long) // and one byte for trailing null (as the ASCII string will be// null terminated).

// Set the privateData length privateData.length = (unsigned short) strlen(&privateData.data[1]) + 2; }

else {

// This case should not happen as such exit(-1); } }

else {

// Exit as user do not want to continue. exit(-1); } }// privateData buffer contains required private data negotiation information.// privateData buffer can be passed in acsOpenStream() method as demonstrated// in

Code Snippet 19: Passing Private Data Negotiation Information Code Example

Page 37: Application Initialization using Avaya AE Services TSAPI ... · Application Initialization using Avaya AE Services TSAPI SDK for Windows A Devconnect Tutorial Table of Contents ...

avaya.com

37

After sending a TSAPI Service request for negotiating Private Data in the acsOpenStream() method, the TSAPI

application should verify that the Private Data information in the confirmation event of acsOpenStream (i.e., in

ACSOpenStreamConfEvent) received from the AE Service server as outlined below.

• The length field of Private Data received should be greater than 0.

• The ‘vendor’ field of Private Data should be set to “ECS”.

• The first byte of the ‘data’ field of Private Data should be a one byte discriminator PRIVATE_DATA_ENCODING.

• Additionally, ‘data’ field should contain the Private Data version (PDV) number as requested in the

acsOpenStream() method.

Code Snippet 20: Negotiating Private Data Code Example illustrates the negotiation of Private Data. Refer to the

Notify() method in Appendix B: Complete Example Code for the complete procedure of verifying that private data is

negotiated correctly.

// CheckPrivateDataVersion: This method demonstrates how an application can verify// that private data version is negotiated correctly. This method only handles// ACS_OPEN_STREAM_CONF event for demonstration purpose. Refer Notify() method // in complete example code for full implementation. // @acsHandle: Pass handle to active ACS stream.// @a_pCstaEvent: Pass CSTA Event object that was retrieved using either // acsGetEventBlock() or acsGetEventPoll() method. // @a_pPrivateData: Pass private data buffer pointer that was returned // by either acsGetEventBlock() or acsGetEventPoll() method. // @a_nOpenStreamInvokeID: Pass invokeID value returned by acsOpenStream() method. // @a_pPDVRequested: Pass private data version that user has requested while // calling acsOpenStream() method. void CheckPrivateDataVersion(ACSHandle_t acsHandle, CSTAEvent_t* a_pCstaEvent, ATTPrivateData_t* a_pPrivateData,

int a_nOpenStreamInvokeID,

Page 38: Application Initialization using Avaya AE Services TSAPI ... · Application Initialization using Avaya AE Services TSAPI SDK for Windows A Devconnect Tutorial Table of Contents ...

avaya.com

38

char* a_pPDVRequested) {

// Checking for Confirmation event for the Open Stream request switch(a_pCstaEvent->eventHeader.eventClass)

{ case ACSCONFIRMATION:

{ switch(a_pCstaEvent->eventHeader.eventType)

{ case ACS_OPEN_STREAM_CONF:

{ if(a_nOpenStreamInvokeID ==

a_pCstaEvent->event.acsConfirmation.invokeID) { cout << endl <<" acsOpenStremConfEvent received - Stream"

" opened successfully."<<endl; cout << " API Version: " << a_pCstaEvent->event.acsConfirmation.u.acsopen.apiVer << endl; cout << " Library Version: " << a_pCstaEvent->event.acsConfirmation.u.acsopen.libVer << endl << endl;

// verify that Private Data is correctly negotiated.

// 1st check the length of the Private Data received if (a_pPrivateData->length <= 0)

{ cout << endl << " Private Data length is zero"

" in acsOpenStreamConf event. Private data" " is not sent as a part of this event.";

// As this application is making use of private// data features, in this condition it is// appropriate to close the application as the // private data is not negotiated successfully. // This could happen if you send a PDV which is // not in range of PDV that AE Services server // supports e.g. "10-25", "0-5", "0", "10" etc

// hanlde error condtion ( abort the Stream ) // return error

// If we do not close application and use PD // feature, the request in which we are using // PD feature will fail. In this example,// cstaMonitorDevice method will fail.

}

// 2nd Check the vendor String

if ( strcmp(a_pPrivateData->vendor,ECS_VENDOR_STRING) != 0 ) {

// hanlde error condtion ( abort the Stream ) // return error

}

// 3rd check the One byte descriminator if ( a_pPrivateData->data[0] != PRIVATE_DATA_ENCODING )

{ // handle error condtion ( abort the Stream ) // return error

} else

{

Page 39: Application Initialization using Avaya AE Services TSAPI ... · Application Initialization using Avaya AE Services TSAPI SDK for Windows A Devconnect Tutorial Table of Contents ...

avaya.com

39

// Retrieving the Private Data cout <<" PrivateData = VENDOR: "<< a_pPrivateData->vendor << endl;

// Checking private data version, whether // it is same as requested or not. char cPDVReturned = a_pPrivateData->data[1];

// To hold returned PDV as number int nReturnedPDV = atoi(&cPDVReturned);

if(strchr(a_pPDVRequested, '-') == NULL) {

// Requested version is specific i.e. does not contain '-' int nRequestedPDV = atoi(a_pPDVRequested);

if(nRequestedPDV == nReturnedPDV) { cout <<" Private data version negotiation is "

"successful."; cout <<" Negotiated private data version is: " << cPDVReturned << endl; }

else { cout <<" Private data version negotiation failed.";

// This is an error condition where AE Server does // not support the PDV requested.

} }

else {

// A range of PDV is requested

// Make a copy of requested PDV value, this // variable will also store first part of requested PDV // after call to strtok_s. char* szFirst = _strdup(a_pPDVRequested); // To store second part of requested PDV char* szSecond;

// strtok_s method is used to split string// which is of format "m-n". This method // will copy m in szFirst and n in szSecond.

strtok_s(szFirst, "-", &szSecond);

int nMinVersion = atoi(szFirst); int nMaxVersion = atoi(szSecond);

// compare value of m and n with // PDV returned. if(nReturnedPDV >= nMinVersion

&& nReturnedPDV <= nMaxVersion ) { cout <<" Private data version negotiation is "

"successful."; cout <<" Negotiated private data version is: " << cPDVReturned << endl; }

else { cout <<" Private data version negotiation failed.";

Page 40: Application Initialization using Avaya AE Services TSAPI ... · Application Initialization using Avaya AE Services TSAPI SDK for Windows A Devconnect Tutorial Table of Contents ...

avaya.com

40

// This is an error condition where AE Server does // not support the PDV requested.

} }// End of else }// End of else } // End of invokeID if } // End of ACS_OPEN_STREAM_CONF case } // End of eventType Switch } // End of case } // End of eventClass Switch } // End of method

Code Snippet 20: Negotiating Private Data Code Example

5.2 Sending a Request Containing Private Data Once Private Data has been negotiated correctly, the application can send the Private Data in the TSAPI request to the TSAPI server.

For example, in case the TSAPI application needs to set the Agent’s work mode, it can be done using the attV6SetAgentState() method. This method encodes the work mode in Private Data. After the work mode is encoded using the attV6SetAgentState() method, Private Data can be used in the cstaSetAgentState() method to set the Agent’s work mode.

The code snippet below shows how to encode the Agent’s work mode and pass it into the cstaSetAgentState() method to set the Agent’s work mode.

Code Snippet 20: Negotiating Private Data Code Example

5.2 SENDING A REQUEST CONTAINING PRIVATE DATA

Once Private Data has been negotiated correctly, the application can send the Private Data in the TSAPI request to

the TSAPI server.

For example, in case the TSAPI application needs to set the Agent’s work mode, it can be done using the

attV6SetAgentState() method. This method encodes the work mode in Private Data. After the work mode is encoded

using the attV6SetAgentState() method, Private Data can be used in the cstaSetAgentState() method to set the

Agent’s work mode.

Code snippet 21 shows how to encode the Agent’s work mode and pass it into the cstaSetAgentState() method to

set the Agent’s work mode.

// SetAgentState: This method demonstrates use of attV6SetAgentState()// method to encode the Agent’s work mode. This method also demonstrates // use of cstaSetAgentState() method to set the Agent’s work mode. // @acsHandle: Pass handle to active ACS stream.bool SetAgentState(ACSHandle_t acsHandle) { InvokeID_t ulinvokeID; // APP_GEN/LIB_GEN DeviceID_t szDeviceID = "40010"; // Agent Terminal PrivateData_t privateData; // Privatedata

long lReasonCode = 1; // Reason code single digit 1-9 AgentMode_t enumAgentMode; // the mode in which Agent logs in AgentPassword_t szAgentPassword =""; // Agent Password AgentID_t szAgentID = "50001"; // Store the AgentID AgentGroup_t szAgentGroup; // Hunt Group Extension (optional) ATTWorkMode_t enumWorkMode; // “AutoIn”/”ManualIn” etc RetCode_t nRetCode; // return value from the API

enumAgentMode = AM_LOG_IN; // Requested Agent Mode,// allows agent to log in

Page 41: Application Initialization using Avaya AE Services TSAPI ... · Application Initialization using Avaya AE Services TSAPI SDK for Windows A Devconnect Tutorial Table of Contents ...

avaya.com

41

// attV6SetAgentState(privatedata, workMode, reasoncode,enablePending) // this method is used here to set the work mode for Agent. // work mode is g3 Private Data variable, thus need to be set using this // method. V6 method is used as this Structure is retained for further// PDV environment (i.e. PDV 7 and PDV 8) for setting Agent work mode.

enumWorkMode = WM_AUTO_IN; // for “AutoIn mode” // enumWorkMode = WM_MANUAL_IN; // Use for “Manual In mode”

nRetCode = attV6SetAgentState((ATTPrivateData_t *)&privateData, enumWorkMode, lReasonCode, FALSE // To enable pending );

if (nRetCode < 0) {

// Error encoding private datareturn false;

}

// Using privateData that contains encoded Agent’s work mode nRetCode = cstaSetAgentState(acsHandle, (InvokeID_t)ulinvokeID, (DeviceID_t *)szDeviceID, enumAgentMode, (AgentID_t *)&szAgentID, (AgentGroup_t *)&szAgentGroup, (AgentPassword_t *) &szAgentPassword, (PrivateData_t *)&privateData );

if (nRetCode < 0) {

// error setting the agent state cout<<" Error while setting Agent State " <<endl; cout<<" Error Return Code: " <<nRetCode;

// handle error return false;

} return true;

}// End of method

Code Snippet 21: Sending Private Data Request Code Example

5.3 Retrieving Private Data from an Event When an event, either CONFIRMATION or UNSOLICITED, is retrieved from the TSAPI Client library queue using either the acsGetEventBlock() or the acsGetEventPoll() methods, the application can use the following steps to extract Private Data information from the event:

1) The application should first check the length of the Private Data returned.

2) The application should then pass the Private Data to the attPrivateData() method for decoding. This method on success will return the Private Data in a structure defined as ATTEvent_t.

3) The application should check the private event type and extract the information.

Code Snippet 21: Sending Private Data Request Code Example

5.3 RETRIEVING PRIVATE DATA FROM AN EVENT

When an event, either CONFIRMATION or UNSOLICITED, is retrieved from the TSAPI Client library queue using either

the acsGetEventBlock() or the acsGetEventPoll() methods, the application can use the following steps to extract

Private Data information from the event:

1. The application should first check the length of the Private Data returned.

2. The application should then pass the Private Data to the attPrivateData() method for decoding. This method on

success will return the Private Data in a structure defined as ATTEvent_t.

3. The application should check the private event type and extract the information.

Please note that for an ACS confirmation event, the Private Data information is not encoded hence the application

only need to check the length of the Private Data before retrieving Private Data information. Code Snippet 20:

Page 42: Application Initialization using Avaya AE Services TSAPI ... · Application Initialization using Avaya AE Services TSAPI SDK for Windows A Devconnect Tutorial Table of Contents ...

avaya.com

42

Negotiating Private Data Code Example demonstrates extracting the Vendor and Private Data version parameters

from the ACS_OPEN_STREAM_CONF (ACS Confirmation) event.

In case when an application receives a CSTA CONFIRMATION or UNSOLICITED event, the application needs to follow

all the three steps as mentioned above.

A sample code snippet to demonstrate how an application can decode and extract private data information from

the CSTA_DELIVERED (CSTA UNSOLICITED) event is given below:

// <summary> // This method demonstrates the procedure to extract the private data// information from delivered event (UNSOLICITED). // </summary> // <param name="cstaEvent"> Pointer to CSTAEvent_t object that contains event’s // information</param> // <param name="privateData"> Pointer to ATTPrivateData_t object that contains // private data information.</param> void ExtractPrivateDataInformation(CSTAEvent_t* cstaEvent, ATTPrivateData_t* privateData){

// Check to event type. switch(cstaEvent->eventHeader.eventType)

{ case CSTA_DELIVERED:

{ // Delivered event received

LocalConnectionState_t connectionState; // To store the connection state connectionState = cstaEvent->event.cstaUnsolicited.u.delivered. localConnectionInfo; CSTAEventCause_t eventCause; // To store the event cause eventCause = cstaEvent->event.cstaUnsolicited.u.delivered.cause;

// check the connection state and cause for the event if( connectionState == csAlerting && eventCause == ecNewCall )

{ // Retrieving the information associated with this event long lcallID = cstaEvent->event.cstaUnsolicited.u.delivered.

connection.callID; char* szCallingDeviceID = cstaEvent->event.cstaUnsolicited.u.

delivered.callingDevice.deviceID; char* alertingDevice = cstaEvent->event.cstaUnsolicited.u.

delivered.alertingDevice.deviceID;

cout<<" An incoming Call with CallID "<<lcallID<<" received" <<" from "<<szCallingDeviceID<<" to " << alertingDevice << endl;

// check the privateData length if ( privateData->length > 0 )

{ // Event buffer that will contain the decoded private data information.

ATTEvent_t attEvent;

Page 43: Application Initialization using Avaya AE Services TSAPI ... · Application Initialization using Avaya AE Services TSAPI SDK for Windows A Devconnect Tutorial Table of Contents ...

avaya.com

43

// Check to ensure that private data is successfully decoded. if ( attPrivateData(privateData, &attEvent) == ACSPOSITIVE_ACK )

{ // check the event type if ( attEvent.eventType == ATT_DELIVERED )

{ // This sample code snippet shows how to // extract UCID information from private data, // other application can similarily extract other private data // information as required.

// extract the Universal Call Identifier (UCID) char* UCID = attEvent.u.deliveredEvent.ucid;

cout << " The UCID is: " << UCID; } // End of if } // End of if

else {

// Decoding Error. cout << " An error occured while decoding"

" private data." << endl; } }// End of outer if

else {

// The event does not contain any private Data. } } // End of if

break; }// End of case

// Application can add other cases for processing other events as needed. }// End of switch }// End of method

Code Snippet 22: Private Data Information Extraction Code Example

Section 6: Setting Up the TSAPI Programming Environment

This chapter examines the TSAPI Client and TSAPI SDK contents along with changes required in the configuration file.

To set the TSAPI programming environment, it is required to install the TSAPI Client and the SDK and also make

some changes in the configuration file. The TSAPI Client is required for executing a TSAPI application while the

TSAPI SDK is required for developing a TSAPI application.

Following are the basic steps to set up the TSAPI environment:

• Installing the TSAPI Client.

• Installing the TSAPI SDK.

• Changes to be made in the configuration file i.e., TSLIB.INI.

Please refer to reference [2] for more information on installing the TSAPI Client and the SDK.

Page 44: Application Initialization using Avaya AE Services TSAPI ... · Application Initialization using Avaya AE Services TSAPI SDK for Windows A Devconnect Tutorial Table of Contents ...

avaya.com

44

Note: The TSAPI SDK and TSAPI Client may be obtained via the Avaya DevConnect Program for either Windows

32-based operating systems, or as an OS-independent version used for Linux development. The TSAPI Client is

available for download from the DevConnect portal. The TSAPI SDK is orderable via the DevConnect procurement

benefits (or authorized Avaya BusinessPartners).

The following sub-sections present a description of the components and contents that are copied on the system

while installing the TSAPI Client and SDK.

6.1 TSAPI CLIENT COMPONENTS

The TSAPI Client provides applications access to Avaya Communication Manager call processing. The primary

component of the TSAPI Client is the TSAPI library. The TSAPI library is the C/C++ library of function calls that

enables an application to request different services provided by TSAPI.

Additionally, the TSAPI Client provides access to Avaya Private Data. Avaya Private Data provides access to

specialized features of Avaya Communication Manager.

The TSAPI Client interacts with TSAPI Service running on AE Services server. AE Services server interacts with

Avaya Communication Manager to provide call processing services. The TSAPI Client must be installed on the

machine for a TSAPI application to run in an AE Services/Communication Manager environment.

The following components are available after the TSAPI Client is installed:

• TSLIB.INI: This configuration file contains a list of the AE Services servers offering telephony services via TCP/IP.

Either Fully Qualified Domain Name (FQDN) or IP address of AE Services server can be used in the list. Instead of

each workstation maintaining its own list of servers, a shared tslib.ini file can be placed on a network file system.

• OpenSSL License: This file contains information about the terms of the license.

• TSAPI Client Readme: This file contains updated information about the TSAPI Client.

• TSAPI Spy: This application can be used to obtain a trace of messages flowing between applications and TSAPI

Service. This tool can be helpful in troubleshooting communication issues between the TSAPI Client library and

AE Services server.

• TSAPI Test: This is a TSAPI test application which can make call from one extension to another. This application

is useful to verify whether the TSAPI Client setup is correctly configured.

6.2 TSAPI SDK COMPONENTS

The AE Services Telephony Services API (TSAPI) SDK is available to developers to help them in developing the

applications that access the AE Services’ TSAPI Service. The TSAPI Client is a prerequisite for installing and using

the TSAPI SDK – developers must install the TSAPI Client first.

The TSAPI SDK components that are installed by default are:

• Sample Code: This directory contains sample code for developing various applications using Avaya TSAPI.

• ReadMe file: This file contains updated information about the Avaya TSAPI SDK.

Page 45: Application Initialization using Avaya AE Services TSAPI ... · Application Initialization using Avaya AE Services TSAPI SDK for Windows A Devconnect Tutorial Table of Contents ...

avaya.com

45

• TSAPI Exerciser: The Application Enablement (AE) Services TSAPI Exerciser is a Windows application that

enables the user to invoke TSAPI methods interactively. The TSAPI Exerciser is meant to be used to help TSAPI

application developers discover how to use the API to access information and invoke requests.

• Apart from this, headers and libraries are also installed in the same folder where the sample code resides.

6.2.1 TSAPI SDK Header Files

The TSAPI SDK header files contain coding structures needed for designing and maintaining the applications. For

designing and updating the application with Private Data, the attpriv.h and attpdefs.h header files are used.

• attpriv.h: The attpriv.h file contains the Protocol Data Units (PDU) structures for the PDUs that are defined in the

attpdefs.h file.

• attpdefs.h: The attpdefs.h file contains the definitions of the Protocol Data Units (PDUs) that are used for Private

Data version control. Each PDU in the attpdefs.h file has a PDU number associated with it. The PDU numbers

with the highest values represent the latest version of Private Data for a given service, confirmation event, or

unsolicited event.

6.2.2 TSAPI Service Client Libraries

The TSAPI Service client libraries provide a set of functions that act as an interface between itself and the client

applications (Table 3). Applications use these functions to establish an authorized connection with TSAPI Service

and to send telephony control messages (CSTA messages) to Avaya Communication Manager. The TSAPI SDK

library files are import libraries.

Library Name DescriptionCSTA32.DLL Contains TSAPI functions (CSTAServiceName) and the ACS Service name services.

ATTPRV32.DLL Contains Private Data encoding and functions (ATTServiceName).

Table 3 : TSAPI Client libraries from the Win32 TSAPI SDK

6.3 CHANGES TO THE FILE TSLIB.INIOnce the TSAPI Client is installed, developers also need to change the TSLIB.INI file (File 1) to use the correct

AE Services’ Fully Qualified Domain Name or IP address and port number. The following parameters need to be

changed to accomplish this:

• Telephony Servers: This is a mandatory parameter and should be set to the Fully Qualified Domain Name or IP

address of the AE Services server.

• Shared Admin: This section is for sharing a single copy of the TSLIB.INI file among all the clients. This section

contains a pointer to the server configuration file that contains the Fully Qualified Domain Name or IP address

of the AE Services server.

The TSLIB.INI file is located in the <Installation Path>/AE Services/TSAPI Client subdirectory.

Page 46: Application Initialization using Avaya AE Services TSAPI ... · Application Initialization using Avaya AE Services TSAPI SDK for Windows A Devconnect Tutorial Table of Contents ...

avaya.com

46

[Telephony Servers] ; This is a list of the servers offering Telephony Services via TCP/IP. ; Either domain name or IP address may be used; default port number is 450 ; The form is: host_name=port_number. ; For example: ; tserver.mydomain.com=450 ; 127.0.0.1=450

192.168.17.128=450

; The entry above indicates that the TSAPI Client can connect to a machine on ; port 450 and IP address of machine is 192.168.17.128. This is the machine on which; TSAPI Server will be running.

[Shared Admin] ; Instead of each workstation maintaining its own list of servers, a shared ; tslib.ini file may be placed on a network file system, for example: ;

; tslib.ini=n:\csta\tslib.ini

; This entry overrides the [Telephony Servers] section, if any.

File 1: TSLIB.INI file

File 1: TSLIB.INI file

Section 7: A Practical Example

This chapter examines the steps required to implement a telephony-enabled application. Each step will be

described in detail covering its programming aspect.

The objective of this chapter is to describe the steps required to initialize any TSAPI application (the initialization

steps remain the same for all TSAPI applications). After proper initialization, various operations can be performed

as per the business needs by using the methods provided by TSAPI.

The example given below demonstrates how to create an application which will monitor a device (extension)

to explain TSAPI application initialization procedure. This example is named DeviceMonitor. This example is

developed as a console based application in C++ on the Windows platform using Microsoft Visual Studio.

Each step below describes a particular method/concept with the necessary sample code snippets and the

corresponding UI snapshots. Appendix B: Complete Example Code offers a practical code example which is

developed to demonstrate all TSAPI concepts discussed in this tutorial. The code is documented with full

comments to give reader a better understanding of each API and concept.

Note: All the variables used in this example are initialized with sample values for demonstration purposes; these

values need to be changed appropriately when building and executing the code in your own environment.

7.1 CREATING A NEW PROJECT

Using Microsoft Visual Studio, create a new Win32 Console Application project called “DeviceMonitor”. Follow the

steps below to add the TSAPI Client library and header files for using the TSAPI Client library in the application.

Page 47: Application Initialization using Avaya AE Services TSAPI ... · Application Initialization using Avaya AE Services TSAPI SDK for Windows A Devconnect Tutorial Table of Contents ...

avaya.com

47

7.2 ADDING THE TSAPI CLIENT LIBRARY

TSAPI SDK includes two TSAPI Client libraries, namely csta32.dll and ATTPRV32.dll for the Windows operating

system. csta32.dll contains the TSAPI functions (CSTAServiceName) and the ACSService name services. ATTPRV32.

dll contains Private Data encoding and functions (ATTServiceName).

The corresponding library files for the DLLs need to be added into the project’s linker settings as additional

dependencies. These library files (csta32.lib and ATTPRV32.lib) are generally found in C:\Program Files\Avaya\AE

Services\SDKs\TSAPI\Libs (assuming the TSAPI SDK installation drive is C:\).

Note: A linking error will be thrown if the location where these libraries are stored is not correctly mapped with this

application. For information about installed files, see Reference [2], Appendix A.

7.3 ADDING THE INCLUDE DIRECTIVES

There are some header files which have to be included in the application. Their names and brief descriptions are

given below:

a) acs.h: This file contains event structures, macro definitions and ACS methods. This file needs to be included in

all TSAPI based applications always.

b) csta.h: This file defines CSTA events and methods. This file needs to be included if any CSTA service(s) are

requested.

c) attpriv.h: This file contains definitions for Private Data. Only applications which request for Private Data need to

include this file.

Since the demo application is going to use CSTA service (monitoring a device) as well as request Private Data, it is

required to include all the three header files.

#include "acs.h" // Contains event structure and macros definition #include "csta.h" // CSTA Events Defines #include "attpriv.h" // ATT Private Defines

Note: These header files are part of Avaya TSAPI SDK and will be stored in the SDK installation directory.

Generally, this path is C:\Program Files\Avaya\AE Services\SDKs\TSAPI\Hdrs. Add the path to these files to the

additional include directories settings for the project.

At this point, while building the application, it should compile without any error. The reader can now enter all the

code from Appendix B: Complete Example Code into the DeviceMonitor.cpp file created while creating the project,

and compile the executable.

Following sections describe the sample application logic flow. The code snippets shown earlier and referenced

herein contain code for explanatory purposes and are limited to describing a particular functionality.

7.4 REQUESTING TO OPEN A STREAM

To open a stream, use the acsOpenStream() method provided by API Control Service.

Page 48: Application Initialization using Avaya AE Services TSAPI ... · Application Initialization using Avaya AE Services TSAPI SDK for Windows A Devconnect Tutorial Table of Contents ...

avaya.com

48

If the application does not want to use the extended features of Avaya Communication Manager, the application

can open a stream without Private Data. In this case the application should pass NULL in the Private Data

parameter. (For more information on Private Data, see Chapter 5:).

A TSAPI application can open a stream with Private Data, for which the application needs to negotiate Private Data

Version (PDV) while calling the acsOpenStream() method.

In Appendix B: Complete Example Code, a separate method OpenACSStream() is added that contains the code for

invoking the acsOpenStream() method with Private Data negotiation. Please refer the OpenACSStream() method to

see the complete procedure for invoking the acsOpenStream() method.

7.5 RECEIVING AND HANDLING EVENTS

Once the acsOpenStream() method returns successfully, the application needs to check ACSOpenStreamConfEvent

event to determine whether the stream opened successfully or not. Only after the confirmation event is received,

further requests for any service on the opened stream can be made.

Once the acsOpenStream() method returns successfully, use the acsSetESR() method to set up an event handler

which will be called whenever there is an event in the TSAPI Client library event queue. Code Snippet 11

demonstrates how to use the acsSetESR() method. Refer to the OpenACSStream() method in Appendix B: Complete

Example Code for the complete procedure of invoking acsSetESR() method.

After setting the event handler, the callback routine i.e., the ESRCallback() method, will be invoked whenever the

TSAPI Client library receives any event from TSAPI Service. Getting the ESRCallback method called only means

there is an event in the event queue; the event still remains in the queue and it is application’s responsibility to

retrieve the event from the queue (using either the acsGetEventBlock() or acsGetEventPoll() method). Refer to the

Notify() method in Appendix B: Complete Example Code for the procedure of calling the acsGetEventBlock() and

acsGetEventPoll() methods and parameters definition.

7.6 REQUESTING TO START A MONITOR

CSTA Service requests can be sent on the opened ACS stream as soon as the ACSOpenStreamConfEvent event is received.

The following section describes how to request a CSTA Service from TSAPI service. Monitoring a device service is

used for simplicity. However, the same concept applies to request for other services.

The cstaMonitorDevice() method is used to monitor a device (station extension). Code Snippet 14 demonstrates

the code to monitor a device. When the cstaMonitorDevice() method is called, TSAPI Service sends a confirmation

event CSTAMonitorConfEvent event to confirm that the monitor is added successfully on the device. The code to

handle this event is similar to ACSOpenStreamConfEvent.

When an event, for example CSTAMonitorConfEvent event is retrieved from the event queue, information like Private

Data and MonitorCrossRefID can be extracted from the event object. Refer to the Notify() method in Appendix B:

Complete Example Code for the complete procedure of retrieving event information.

Page 49: Application Initialization using Avaya AE Services TSAPI ... · Application Initialization using Avaya AE Services TSAPI SDK for Windows A Devconnect Tutorial Table of Contents ...

avaya.com

49

7.7 REQUESTING TO STOP A MONITOR

To stop monitoring the monitored device, the cstaMonitorStop() method can be used. The StopMonitor() method

in Appendix B: Complete Example Code demonstrates the use of cstaMonitorStop() method. A confirmation event

will be received for a stop monitor request. Please refer the Notify() method in the sample code to see how an

application can handle CSTA_MONITOR_STOP_CONF confirmation event.

7.8 ERROR HANDLING

While working with TSAPI Client library and TSAPI Service, every TSAPI application should be designed to handle any

CSTA or ACS related error. The application is provided an event to report an error as and when the error is occurred.

The ACSUniversalFailureEvent event can occur at any time (unsolicited) and can indicate, among other things, a

failure or loss of the ACS stream with TSAPI Service.

The ACSUniversalFailureConfEvent event can occur at any time in place of a confirmation event for any of the ACS

functions which have their own confirmation event and indicate a problem in the processes of the requested method.

The most common CSTA errors are reported through CSTAUniversalFailureConfEvent, which represents a negative

acknowledgment for any CSTA service.

Please refer the Notify() method in the sample code to see an example of handling ACS_UNIVERSAL_FAILURE_CONF

and CSTA_UNIVERSAL_FAILURE_CONF events.

7.9 REQUESTING TO CLOSE/ABORT A STREAM

The stream should be closed or aborted once the application finishes its operation on the stream opened with the

TSAPI Service or in case of any critical error. The acsCloseSream() or acsAbortStream() method can be used to close

or abort the stream.

Code Snippet 7 and Code Snippet 9 demonstrate the use of acsCloseStream() and acsAbortStream() methods, respectively.

Page 50: Application Initialization using Avaya AE Services TSAPI ... · Application Initialization using Avaya AE Services TSAPI SDK for Windows A Devconnect Tutorial Table of Contents ...

avaya.com

50

7.10 APPLICATION OUTPUT

When successfully compiled, installed and executed, the DeviceMonitor sample application will display output

similar to the following:

Screenshot 1: Sample code’s output

Page 51: Application Initialization using Avaya AE Services TSAPI ... · Application Initialization using Avaya AE Services TSAPI SDK for Windows A Devconnect Tutorial Table of Contents ...

avaya.com

51

Appendix A: Notes

Note 1. What is InvokeID?

Each service request passes an invokeID to distinguish it from other service requests. invokeID provides a way to

match the confirmation event/failure event to the corresponding request. The application should specify a unique

invokeID so that it will be easy to distinguish between the confirmations events.

There are two alternatives provided by the APIs to generate and associate invokeID with the requests. The application

needs to select one of the following invokeID types and set it as invokeIDType in the acsOpenStream request.

1. Application generated invokeID (APP_GEN_ID): When invokeIDtype is set as APP_GEN_ID, the application takes

the responsibility of generating and providing a unique invokeID internally for any service request. Although

taking the responsibility of providing a unique invokeID puts a burden on the application when service requests

correspond to entries in a data structure, it may simplify application design to use indexes into the data

structure as invokeIDs.

2. TSAPI library generated invokeID (LIB_GEN_ID): When invokeIDtype is set as LIB_GEN_ID, the TSAPI Client library

takes care of providing a unique invokeID for any service request made to the AE Services server. Along with

LIB_GEN_ID, if the application supplies an invokeID in the service request, it will be ignored by TSAPI Service.

Library-generated invokeIDs are unique and simplifies the application design.

Refer the Notify() method in the sample code to see how invokeID can be used to match the confirmation event/

failure event to the corresponding request.

Note 2. Common Return Values

For some APIs, their return value depends on the invokeIDtype parameter value passed in the acsOpenStream() method:

• LIB_GEN_ID - If the application passes LIB_GEN_ID for invokeIDtype, when the method completes successfully, the

method will return a positive value, i.e., the invoke identifier. If the method fails, a negative value (<0) will be

returned. For library-generated invoke identifiers, the return value will never be zero (0).

• APP_GEN_ID - If the application passes APP_GEN_ID for invokeIDtype, when the method completes successfully,

the method will return a zero (0) value. If the method fails, a negative value (<0) will be returned. For

application-generated invoke identifiers, the return value will never be positive (>0).

Note 3. Queue Size

The TSAPI Client library maintains a queue for the requests to be sent and a queue for the received messages

or events. The application can decide the maximum size for these queues while opening the Session. If

the application supplies a zero (0) value, then the default queue size will be used. Parameters sendQSize,

sendExtraBufs, recvQSize and recvExtraBufs are used for this purpose. In normal circumstances, the developer need

not increase the size of the queue. However, if the application requires an increase in the size of the queue, it can

be increased using the parameters described above.

When the queue is full, the TSAPI Client library returns the ACSERROR_QUEUE_FULL error. There could be multiple reasons

for this error and it depends on the application; some of the reasons along with the resolution are given below:

Page 52: Application Initialization using Avaya AE Services TSAPI ... · Application Initialization using Avaya AE Services TSAPI SDK for Windows A Devconnect Tutorial Table of Contents ...

avaya.com

52

• The queue will get full in case client library is receiving request with much higher pace than it can actually

process. In such a case, requesting a bigger sized queue with the help of the sendQSize or recvQSize parameter

in acsOpenStream or redesigning the application to manage the request flow can solve this problem.

• The client library can also throw this error because it is unable to dispatch a message to TSAPI Service because

of a potential network issue that is causing a delay in the message flow. The application developer should try to

check the network connection and throughput to verify that it does not have any problem.

Under normal conditions, the default queue size would be adequate. However, if required, the application can

request the Client library to reserve a queue for a specified number of messages using the sendQSize or recvQSize

parameter in the acsOpenStream() method.

It is suggested that the application should be designed such that upon receiving this error, it notifies all the other

modules to stop sending further requests because the client library is full and so it will consume unnecessary

network bandwidth.

Note 4. Accessing a Secured TSAPI Link (Tlink)

The AE Services server administrator can encrypt the client connections for a TSAPI link that the client

applications wish to connect with. See Reference [3], Chapter 2, “Administering TSAPI Links in AE Services OAM”

for more information.

The client application will receive an ACSERR_NOSERVER error if it is trying to access a secured Tlink without

making sure that the following points hold true:

a) The protocol should be mentioned as “CSTA-S” instead of “CSTA” in the used Tlink. For example, assume

that the client application is using a Tlink named “AVAYA#SWITCH#CSTA#SERVERNAME” with the Tlink set

to ‘unencrypted’. If the Tlink is now set to ‘encrypted’, the client application needs to change the Tlink to

”AVAYA#SWITCH#CSTA-S#SERVERNAME”.

b) The TSAPI Client library version must be 4.1.0 or later.

Note 5. Private Data Version Negotiation

To negotiate Private Data Version (PDV) with the AE Services server, the acsOpenStream() method must be called with the

privateData parameter which is of type ATTPrivateData_t structure. The application specifies the acceptable version(s) in the

data field of the ATTPrivateData_t structure. The data field contains a constant PRIVATE_DATA_ENCODING followed by the null

terminated ACSII string containing the version or range of versions. The version string should be passed as formatted. The

AE Services TSAPI SDK provides the attMakeVersionString() method to simplify formatting of the requested version string.

The application can either request for a specific Private Data Version (PDV) (for e.g. “8”) or provide a range of PDV

(for e.g. “3-8”, “5-7”, etc.) during opening of ACS stream. Currently 8 is the highest PDV supported by the AE

Services server. Requested PDV value indicates that the application is compatible with the specified PDV(s).

The requested version is validated at two levels. First the attMakeVersionString() method applies a preliminary

check on the requested version by comparing the requested version with the version that is currently supported by

Page 53: Application Initialization using Avaya AE Services TSAPI ... · Application Initialization using Avaya AE Services TSAPI SDK for Windows A Devconnect Tutorial Table of Contents ...

avaya.com

53

the Client library. The attMakeVersionString() method returns a value that is greater than 0 if it finds the requested

version is in the currently supported PDV range (by the Client library). For example, if the application requests

range “3-8”, and the Client library only supports version till 5, then this method returns a value that is greater

than 0. The attMakeVersionString() method returns 0 that indicates that the requested version is out of supported

range (i.e less than 1 or greater than the currently supported version).

For example, when the Client library supports version up to and including version 5, and the application has requested:

• version “6-8” or

• version 8 (or any single digit value > 5) or

• “10-25”,

then 0 will be returned to the application.

Second validation happens at the AE Services server level. On receiving requested version with open stream

request, the AE Services server validates the requested version by comparing the requested version with the

version that is currently supported by the AE Services server and returns the supported PDV to the application in

ACSOpenStreamConfEvent confirmation event.

When a range of PDV(s) is provided i.e., “3-8”, the AE Services server picks the highest supported version in the

range specified. If the AE Services server does not support the highest version requested then it picks up the next

highest version it supports and returns that to the application in the ACSOpenStreamConfEvent confirmation event.

For example, if the application requests range “3-8”, and the AE Services server only supports version till 5, then

5 will be returned to the application.

When a specific PDV is requested, and AE Services server supports requested version, then the same requested

version will be returned in the ACSOpenStreamConfEvent confirmation event. For example, if the application requests

version “4”, and the AE Services server supports version till 5, then 4 will be returned to the application.

In any of the following conditions,

• The AE Services server does not support any of the versions from the requested range;

• The requested specific version is out of supported range (i.e less than 1 or greater than the currently supported version);

• NULL is passed in the privateData parameter in The length parameter of ATTPrivateData_t structure is set as 0;

a call to the acsOpenStream() method will still be successful, however, in the ACSOpenStreamConfEvent event,

the length of the Private Data buffer will be 0, indicating that the Private Data negotiation is unsuccessful, i.e.

the application will not be able to access any of the private data extended features, such as single step transfer

call, single step conference call, etc. Also, the application will not receive any Private Data information in the

confirmation/unsolicited events from the AE Services server.

When the PDV is correctly negotiated then the application should only request for the features supported by the

negotiated PDV. Request for any feature(s) not supported by the negotiated PDV will result in failure confirmation event.

Page 54: Application Initialization using Avaya AE Services TSAPI ... · Application Initialization using Avaya AE Services TSAPI SDK for Windows A Devconnect Tutorial Table of Contents ...

avaya.com

54

Appendix B: Complete Example Code

To simplify code understanding, the complete example code is provided here. This source code is also available as

a plain text file from the Avaya DevConnect Portal to simplify inclusion into a sample project file.

// DeviceMonitor.cpp : DeviceMonitor is a console based windows application designed // to demonstrate use of some of the common Telephony Services API's functionality// and basic operation. This application demonstrate common initialization process // required for every TSAPI Client application. After initialization this application // demonstrate Monitoring Services functionality by setting a monitor on// a device (Extension). Other appilcations can be designed to use other services// provided by TSAPI. //// Note: Please ensure library files (CSTA32.lib & ATTPRIV.lib)// are included into Linker's "include" option in project setting. // Following are the major TSAPI APIs demonstrated in this application: // 1: Acquire a list of advertised service name using acsEnumServerNames() method. // 2: Open a API Control Services (ACS) stream using acsOpenStream() method. // 3: Set a method to receive event notification from TSAPI Service// using acsSetESR() method. // 4: Retrieve events from Client library's event queue using acsGetEventBlock() // and acsGetEventPoll() method. // 5: Monitor a device (Extension) using cstaMonitorDevice() method. // 6: Stop monitoring monitored device using cstaMonitorStop() method. // 7: Abort the opened ACS stream using acsAbortStream() method. // 8: Close the opened ACS stream using acsCloseStream() method.

#include "stdafx.h"#include <iostream>#include <conio.h>#include <tchar.h>#include <map>using namespace std;

// TSAPI required header files

// Contains event structure and macros definition #include "acs.h"// CSTA Events Defines #include "csta.h" // ATT Private Defines #include "attpriv.h"

// Gloabal variables declaration - Starts Here

// This demo application stores monitor cross reference ID // and InvokeIDs returned from APIs in global variables for // simplicity, other applications should be designed to store // these values in a map or any other data structure.

// Store the Monitor Cross reference ID returned by the Monitor Service CSTAMonitorCrossRefID_t g_lMonitorCrossRefID;

// To store InvokeID for open stream request int g_nOpenStreamInvokeID = 0; // To store InvokeID for close stream request int g_nCloseStreamInvokeID = 0; // To store InvokeID for start monitor device request int g_nStartMonitorInvokeID = 0; // To store InvokeID for stop monitor device request int g_nStopMonitorInvokeID = 0;

// Handle object used to wait for acsOpenStreamConf Event HANDLE g_hOpenStreamConfEvent; // Handle object used to wait for acsCloseStreamConf Event

Page 55: Application Initialization using Avaya AE Services TSAPI ... · Application Initialization using Avaya AE Services TSAPI SDK for Windows A Devconnect Tutorial Table of Contents ...

avaya.com

55

HANDLE g_hCloseStreamConfEvent;// Handle object used to wait for MonitorDeviceConf Event HANDLE g_hMonitorDeviceConfEvent; // Handle object used to wait for MonitorStopConf Event HANDLE g_hMonitorStopConfEvent;

// Contain private data version that is requested by user // for negotiation.Version_t g_szPrivateDataVersion;

// Count for the available service names static int nServicesCount = 0; // Data structure to store service name map<int, char*> serviceNameMap; typedef pair <int, char*> serviceNamePair;

// Gloabal variables declaration - Ends Here

// Method Declaration - Starts Here

// Method to open an ACS stream bool OpenACSStream(ACSHandle_t* a_pAcsHandle);

// Method to monitor a device void MonitorDevice(ACSHandle_t* a_pAcsHandle);

// Method to stop monitoring void StopMonitor(ACSHandle_t* a_pAcsHandle);

// Method to Close an ACS stream void CloseStream(ACSHandle_t* a_pAcsHandle);

// Method to Abort an ACS Stream void AbortStream(ACSHandle_t* a_pAcsHandle);

// Callback function that will be called when an event // is available in Client library event queue void __stdcall ESRCallback (unsigned long esrParam);

// Method to that retrieve the events from Client library event queue // and process each event. void Notify(ACSHandle_t* a_pAcsHandle);

// Initializes application variables bool InitApplication();

// Print error messages and exit the application void PrintErrorAndExit(ACSHandle_t* a_pAcsHandle);

// Enumerate service names registered with TSAPI Service. void EnumerateServiceNames();

// Method Declaration - Ends Here

// This is starting point where the application will begin from int _tmain(int argc, _TCHAR* argv[]) {

// Maximum wait time interval for receiving an event const int APP_DEF_WAIT_TIMEOUT = 5000; // Five seconds

// For variable initialization defined at application scope InitApplication();

cout<<"************************************************************"<<endl;

Page 56: Application Initialization using Avaya AE Services TSAPI ... · Application Initialization using Avaya AE Services TSAPI SDK for Windows A Devconnect Tutorial Table of Contents ...

avaya.com

56

cout<<" TSAPI SAMPLE CLIENT "<<endl; cout<<"************************************************************"<<endl <<endl;

cout << " Listing all advertised service names below:" << endl; EnumerateServiceNames();

// Open an ACS stream to access features supported by a service // that is advertised by AE Services server.

cout << endl << endl << " Trying to Open an ACS Stream...."<<endl<<endl;

// Store handle of the ACS stream ACSHandle_t* pAcsHandle = new ACSHandle_t;

if ( OpenACSStream(pAcsHandle) ) {

// Wait until we receive a confirmation event for// acsOpenStream() request

if(WaitForSingleObject(g_hOpenStreamConfEvent, APP_DEF_WAIT_TIMEOUT) == WAIT_OBJECT_0) {

// Start monitoring a device cout<<" Trying to Monitor a device..." << endl;

MonitorDevice(pAcsHandle);

// Wait until we receive a confirmation event for// cstaMonitorConf() request if(WaitForSingleObject(g_hMonitorDeviceConfEvent, APP_DEF_WAIT_TIMEOUT)

== WAIT_OBJECT_0) {

do {

// This loop run until user press X or x on console, till that// time we will continue receiving monitor event.

cout << endl << " Monitoring is on, Do you want to stop monitoring now?" << endl <<" Please press x or X to stop the Monitor or any other"

" key to continue monitoring..."<<endl;char chInputChar = _getche(); if(chInputChar == 'X' || chInputChar == 'x')

{ break;

} else

{ // Continue with loop

} }while(true);// loop ends when user press X or x

// Stop the Monitor request cout<<endl<<" Trying to Stop the Monitor...."<<endl<<endl; StopMonitor(pAcsHandle);

// Wait until we receive a confirmation event for// cstaMonitorStopConf() request

if(WaitForSingleObject(g_hMonitorStopConfEvent, APP_DEF_WAIT_TIMEOUT) == WAIT_OBJECT_0) { cout << " Application has received monitor closed"

" confirmation event." << endl;

Page 57: Application Initialization using Avaya AE Services TSAPI ... · Application Initialization using Avaya AE Services TSAPI SDK for Windows A Devconnect Tutorial Table of Contents ...

avaya.com

57

}// end of if else

{ cout << " Error: MonitorStopConfEvent event not received"

" in set time limit." << endl; PrintErrorAndExit(pAcsHandle); } }// end of if

else { cout << " Error: MonitorDeviceConfEvent event not received"

" in set time limit." << endl; PrintErrorAndExit(pAcsHandle); }

}// end of ifelse

{ cout << " Error: OpenStreamConfEvent event not received"

" in set time limit." << endl; PrintErrorAndExit(pAcsHandle); }

// Close the ACS stream

cout<<" Trying to close the stream...."<<endl<<endl;

// Close the opened stream CloseStream(pAcsHandle);

if(WaitForSingleObject(g_hCloseStreamConfEvent, APP_DEF_WAIT_TIMEOUT) == WAIT_OBJECT_0) { cout << " Application has received close"

" stream confirmation event." << endl; }// end of if

else { cout << " Error: CloseStreamConfEvent event not received"

" in set time limit." << endl; PrintErrorAndExit(pAcsHandle); } }

else {

// when the application reaches here then that means// the application is not able to send request for Opening the Stream

cout << " Error: Failed to open stream.... "; }

delete pAcsHandle; return 0;

}// end of main void PrintErrorAndExit(ACSHandle_t* a_pAcsHandle) { cout << " Due to the error occured, the application will close now,"

" please retry after some time." << endl;

// As we are closing the application in an error condition // we should abort the ACS stream using acsAbortStream method // which will free the resource immediately.

cout<<" Trying to abort the stream...."<<endl<<endl;

// Abort the opened stream

Page 58: Application Initialization using Avaya AE Services TSAPI ... · Application Initialization using Avaya AE Services TSAPI SDK for Windows A Devconnect Tutorial Table of Contents ...

avaya.com

58

AbortStream(a_pAcsHandle);

exit(-1); }bool InitApplication() {

// The CreateEvent function creates or opens a named or unnamed// event object.

g_hOpenStreamConfEvent = CreateEvent(0,TRUE,FALSE,0); g_hCloseStreamConfEvent = CreateEvent(0,TRUE,FALSE,0); g_hMonitorDeviceConfEvent = CreateEvent(0,TRUE,FALSE,0); g_hMonitorStopConfEvent = CreateEvent(0,TRUE,FALSE,0);

return true;}

// This is the call back method that will be called when// an incoming event is available in the Client library queue. // @param esrParam: acsHandle passed in this parameter. void __stdcall ESRCallback (unsigned long esrParam) { ACSHandle_t* acsHandle = (ACSHandle_t*) esrParam;

// As the event is now available in the Client library's queue, // other applications should be designed cautiously to retrieve // the event and process it without blocking this thread for a // long time. Writing event processing logic (specially when the// logic is lengthy) in a seperate thread is recommended.

// In this example as the event processing logic is simple and not // lengthy, we are calling method directly from this thread only.

Notify(acsHandle); }

// OpenACSStream() method: This method demonstrates the use of acsOpenStream() // method which is used to establish a communication channel between the// application and the TSAPI Service to access the advertised services. bool OpenACSStream(ACSHandle_t* a_pAcsHandle) {

// constants will be used in acsOpenStream method. const int SEND_QUEUE_SIZE = 0; const int RECEIVE_QUEUE_SIZE = 0; const int SEND_EXTRA_BUF_SIZE = 5; const int RECEIVE_EXTRA_BUF_SIZE = 5; const int MINIMUM_LENGTH = 3;

// Store the Return code of the method RetCode_t nRetCode;

// To hold the advertised service name ServerID_t szServiceName;

// To hold CTI user login ID LoginID_t szLoginID;

// To hold CTI user password Passwd_t szPassword;

// To hold authentication information ACSAuthInfo_t authInfo;

// This demo application request user to enter advertised service Name, // login ID and password. Other application can read this information // from configuration file or any other data source as appropriate.

// Request application user to provide advertised service name cout << " Please select a number corresponding to the advertised"

" service name you wish to work with: ";int nChoice;

Page 59: Application Initialization using Avaya AE Services TSAPI ... · Application Initialization using Avaya AE Services TSAPI SDK for Windows A Devconnect Tutorial Table of Contents ...

avaya.com

59

cin >> nChoice; // The key value in the map starts with 1 and maximum key value // will be one more than size of map. if(nChoice > 0 && nChoice < ((int) serviceNameMap.size() + 1))

{ // Getting service name corresponding to the number choosen// by the user from the map.

strcpy_s(szServiceName, serviceNameMap[nChoice]); }

else { cout << endl << " An incorrect choice made," << " using a default service name." << endl;

// Using default Service name in case user specify incorrect string strcpy_s(szServiceName, "AVAYA#CMSIM#CSTA#AESSIM"); }

// Use acsQueryAuthInfo( ) to determine the login and password requirements // when opening an ACS stream to a particular advertised CSTA service.

nRetCode = acsQueryAuthInfo((ServerID_t*) szServiceName, &authInfo); if(nRetCode != ACSPOSITIVE_ACK)

{ cout << " Error: acsQueryAuthInfo method failed."; }

switch(authInfo.authType) {

case needLoginIdAndPasswd: {

// We should request user to enter both login ID// and password.

cout << endl << " Please enter CTI User login ID: ";// To hold login ID

cin >> szLoginID;

cout << endl << " Please enter CTI User password: ";// To hold password

cin >> szPassword;

break; }

case authLoginIdOnly: {

// We should request user to enter only login ID. cout << endl << " Please enter login ID: ";

// To hold login cin >> szLoginID;

break; }

default: {

// Default login ID for this application strcpy_s(szLoginID, "avaya");

// Default password for this application strcpy_s(szPassword, "Avayapassword@123"); } }

// Assuming login ID and Password minimum length is// greater than three char. Using default if user do not enter // correct credentials. if(strlen(szLoginID) < MINIMUM_LENGTH)

{

Page 60: Application Initialization using Avaya AE Services TSAPI ... · Application Initialization using Avaya AE Services TSAPI SDK for Windows A Devconnect Tutorial Table of Contents ...

avaya.com

60

cout << endl << " An incorrect LoginID is supplied" << ", using default LoginID.";

// Default login ID for this application strcpy_s(szLoginID, "avaya"); }

if(strlen(szPassword) < MINIMUM_LENGTH) { cout << endl << " An incorrect Password is supplied" << ", using default Password.";

// Default password for this application strcpy_s(szPassword, "Avayapassword@123"); }

// To hold the Application Name, the system uses the application // name on certain administration and maintenance status displays.

AppName_t szAppName = "DeviceMonitor"; // Can be empty string

// This parameter contains an ASCII string that is formatted with no spaces,// as follows: TSn-n:5 // where: // TS is a fixed constant (use uppercase characters). // n is a number indicating the TSAPI version // - (hyphen) character indicates a range of versions. // : (colon) character indicates a list of versions. // Example // The following example depicts how an application specifies that it can use// TSAPI versions 1 through 3 (1,2, and 3) and version 5. // TS1-3:5

Version_t szApiVersion = "TS1-2";

// Set a unique value in this parameter in case Application generated // invokeID is used. // As in this example we are using Library generated invokeID, this // parameter value is set to zero.

InvokeID_t lInvokeID = 0;

// Below code demonstrate the process to send private data version// negotiation information in the acsOpenStream() method.

// ATT service request private data buffer ATTPrivateData_t privateData;

// Set the vendor field to 'VERSION' strcpy_s(privateData.vendor, "VERSION");

// Set the data field to a one byte discriminator// PRIVATE_DATA_ENCODING followed by an ASCII string identifying// the version of the private data. Setting the first byte to// PRIVATE_DATA_ENCODING

privateData.data[0] = PRIVATE_DATA_ENCODING;

// A special function is used to convert version string into the format// required by the acsOpenStream function.

cout << endl << " Please enter private data version: "; cin >> g_szPrivateDataVersion;

// Setting the formatted PDV version starting from second byte in the data// field. if((attMakeVersionString(g_szPrivateDataVersion, &(privateData.data[1])))

> 0 ) {

// Setting the privateData length, adding 2 extra bytes here, one byte for

Page 61: Application Initialization using Avaya AE Services TSAPI ... · Application Initialization using Avaya AE Services TSAPI SDK for Windows A Devconnect Tutorial Table of Contents ...

avaya.com

61

// element at zero location (i.e. data[0] as it is one byte long) // and one byte for trailing null (as the ASCII string will be// null terminated).

privateData.length = (unsigned short) strlen(&privateData.data[1]) + 2; }

else {

// attMakeVersionString failed due to incorrect version passed. cout << endl << "attMakeVersionString() method failed..."; cout << endl << "If you want to continue, a default Private Data"

" Version string (3-8) will be used." " Press y/Y to continue or any other key to exit the " " application... ";

char cContinue = _getche(); if(cContinue == 'Y' || cContinue == 'y')

{ // If the attMakeVersionString fails, to continue without private data// set the privateData.length to 0. // Note that in this case private data will not be available to the// application. ACSOpenStreamConfEvent event will receive 0 length PD. // privateData.length = 0;

// As this application make use of private data, setting PDV to a// default value "3-8" in this case.

strcpy_s(g_szPrivateDataVersion, "3-8");

// Calling attMakeVersionString again with default PDV if ( (attMakeVersionString(g_szPrivateDataVersion,

&(privateData.data[1]))) > 0 ) { privateData.length =(unsigned short)strlen(&privateData.data[1]) + 2; }

else {

// Probably using TSAPI client library from the older version exit(-1); } }

else {

// Exit as user do not want to continue. exit(-1); } }

bool bIsSuccess = false;while(!bIsSuccess)

{

// Open a stream with Private Data negotiation & with library// generated InvokeID. This method will returns invokeID on success // as LIB_GEN_ID is used. The invokeID will be stored in nRetCode.

// If the application does not wish to receive Private Data, it should // pass 0 in privateData parameter.

nRetCode = acsOpenStream(a_pAcsHandle, LIB_GEN_ID, // Library takes the control for generating InvokeID. lInvokeID, // This param is ignored when the 2nd parameter is LIB_GEN_ID ST_CSTA, // requesting CSTA stream type. &szServiceName, // CTI Link name "AVAYA#SWITCH1#CSTA#SERVERNAME1" &szLoginID, // CTI user login ID &szPassword, // CTI user password

Page 62: Application Initialization using Avaya AE Services TSAPI ... · Application Initialization using Avaya AE Services TSAPI SDK for Windows A Devconnect Tutorial Table of Contents ...

avaya.com

62

&szAppName, // name of the application ACS_LEVEL1, // LIB Version, will be ignored &szApiVersion, // API Version SEND_QUEUE_SIZE,// send queue size using default 0 SEND_EXTRA_BUF_SIZE, // send extra buf size RECEIVE_QUEUE_SIZE, // receive queue size using default 0 RECEIVE_EXTRA_BUF_SIZE, // receive extra bufs (PrivateData_t *)&privateData // buffer for Private Data );

// If nRetCode is returned as positive value then this suggests// that TSAPI Client Library has accepted the method and // has placed the request in the queue for sending the// request to TSAPI Service. // If negative value is returned then TSAPI CLient library // has rejected the request and has provided the error code.

if(nRetCode > 0) // acsOpenStream returned successfully {

// storing invoke ID for future use g_nOpenStreamInvokeID = (int) nRetCode; bIsSuccess = true; // Stop the loop }

else if(nRetCode < 0) // acsOpenStream failed {

// Other applications should do the error handling as per need// like logging error in a log file or event viewer. For some of these// error you can take corrective action and retry e.g. if you receive// ACSERR_APIVERDENIED, you can try with another version. switch(nRetCode)

{ case ACSPOSITIVE_ACK:

{ // The function is successful

bIsSuccess = true; // Stop the loop break;

} case ACSERR_APIVERDENIED:

{ // This return value indicates that the API Version requested is // invalid and not supported by the existing API Client Library.

cout << endl << " Error: acsOpenStream method failed to" " open stream.." << endl;

// Requesting user to enter TSAPI version again. cout << " Error: API Version is incorrect. Trying again." << endl;

bIsSuccess = false; // Continue the loop break;

} case ACSERR_BADPARAMETER:

{ // One or more parameters invalid. // Validate supplied parameter with the help of// TSAPI Exerciser tool. break;

}default:

{ // Some unhandled error occured const int SLEEP_TIME = 3000;

cout << endl << " Error: acsOpenStream method failed to open stream.."; cout << endl << " Error code: " << nRetCode; Sleep(SLEEP_TIME);

return false;

Page 63: Application Initialization using Avaya AE Services TSAPI ... · Application Initialization using Avaya AE Services TSAPI SDK for Windows A Devconnect Tutorial Table of Contents ...

avaya.com

63

} } }

else // case when nRetCode == 0 {

// Not possible as LIB_GEN_ID is used in this example. } }

// acsSetESR(): This method is used to register a callback method with// Client library to receive a notification when an event is available // in the Client library’s event queue. // If the method is successful, the Client library will call ESRCallback // method whenever there is an event is available in its event queue. // @a_pAcsHandle: Handle returned by the acsOpenStream() method // @ESRCallback: Call back routine invoked when there is an incoming event. // @a_pAcsHandle: An open ACS stream handle is passed in this parameter // whick will be passed in ESRCallback method as parameter. // @notifyAll: TRUE indicates that the ESRCallback will be called// for each new event that arrives in Client library's event queue. // A FALSE value will indicate that the ESRCallback will // only be called each time the Client library's event queue becomes // non-empty.

nRetCode = acsSetESR(*a_pAcsHandle, ESRCallback, (unsigned long)a_pAcsHandle, TRUE);

// Verification for the positive response if(nRetCode != ACSPOSITIVE_ACK)

{ cout<<" ERROR: acsSetESR() method return with an error.";

if(nRetCode == ACSERR_BADHDL) { cout<<" ulAcsHandle being used is not a valid handle"<<endl; }

else { cout << " acsSetESR() failed with unknown error. " << endl; cout << " Error code: " << nRetCode; }

} return true;

}

// MonitorDevice() : This method demonstrates the use of cstaMonitorDevice()// method which is used to monitor the device (Extension) and to receive the// events that arrive at the device after monitor request acknowledged. void MonitorDevice(ACSHandle_t* a_pAcsHandle) {

// Set the DeviceID of the Deivce to be monitored DeviceID_t szDeviceID = "40011"; // Default device ID cout << " Please enter device ID of the device to be monitored: \a"; cin >> szDeviceID;

// Store the return code of the method RetCode_t nRetCode = 0;

CSTAMonitorFilter_t filter; // Store the Montor Filter setting

// Pass 0 for a specific filter category or pass NULL for the filter parameter.

// Call filters are supported for station device.

Page 64: Application Initialization using Avaya AE Services TSAPI ... · Application Initialization using Avaya AE Services TSAPI SDK for Windows A Devconnect Tutorial Table of Contents ...

avaya.com

64

filter.call = cfQueued; // Settting filter for Call Queued event.

// The Agent Filter is supported only for ACD Split devices. filter.agent = 0; // We are using a extension device in this example

// The Feature Filter and Maintenance Filter are not supported. filter.feature = 0; filter.maintenance = 0;

// A zero Private Filter means that the application wants to receive // the private events. If Private Filter is non-zero, private events// will be filtered out.

filter.privateFilter = 0;

// cstaMonitorDevice(): Sending a request to monitor a device. // @a_pAcsHandle : Handle returned from the acsOpenStream() method // @szDeviceID : Specifies the DeviceID of the device to be monitored // @filter : Filter to be set for receiving the events. if NULL is passed// then No filter will be set and application will receive event // reports for all events. // @privateData: Not passing private data with this request.

nRetCode = cstaMonitorDevice( *a_pAcsHandle, // ACS Stream handle 0, // Invoke ID is ignored, as it is library generated &szDeviceID, // ID of the device to be monitored &filter, // Filter setting that will apply on monitor NULL // Private data not passed with this request );

if(nRetCode < 0) { cout<<" Failed to monitor device ID: "<< szDeviceID <<endl; cout<<" Error code: " << nRetCode; }

else {

// cstaMonitorDevice returned successfully g_nStartMonitorInvokeID = nRetCode; } }

// StopMonitor() : This method demonstrates the use of cstaMonitorStop() method // which is used to stop the monitor request for a perticular device. // After invoking this method application will not receive any // event for the device on which monitor service was activated. void StopMonitor(ACSHandle_t* a_pAcsHandle) {

// cstaMonitorStop(): Request to stop the monitor on device. // @a_pAcsHandle: Handle returned from the acsOpenStream() method // @invokeID: Setting it to zero as Library generated ID is used in this // example. // @g_lMonitorCrossRefID: Specifies the Monitor cross reference ID received// in the cstaMonitorDeiviceConf event. // @privateData: - Presently this parameter is ignored so please pass NULL // in this parameter for cstaMonitorStop() method

// Store the Return code of the method RetCode_t nRetCode; nRetCode = cstaMonitorStop (*a_pAcsHandle, 0, g_lMonitorCrossRefID, 0);

// Checking for the negative response

Page 65: Application Initialization using Avaya AE Services TSAPI ... · Application Initialization using Avaya AE Services TSAPI SDK for Windows A Devconnect Tutorial Table of Contents ...

avaya.com

65

if ( nRetCode < 0) { cout<<" Failed to stop monitor"<<endl; cout<<" Error Code :"<<nRetCode;

return; }

else {

// Request is successful. g_nStopMonitorInvokeID = nRetCode; }

}// AbortStream() : This method demonstrates the use of acsAbortStream() method. void AbortStream(ACSHandle_t* a_pAcsHandle) {

// acsAbortStream(): Request to abort an ACS stream. No confirmation event // will be provided for this method. // @a_pAcsHandle: Handle returned from the acsOpenStream() method // @privateData: - Presently this parameter is ignored so please pass NULL // in this parameter for acsAbortStream() method

RetCode_t nRetCode = acsAbortStream(*a_pAcsHandle, NULL);

// Checking for the negative response if(nRetCode<0)

{ if(nRetCode==ACSERR_BADHDL)

{ cout<<" The ACS Handle is invalid "<<endl<<endl; }

else { cout<< " acsAbortStream() failed with unknown error. " << endl; cout << " Error code: " << nRetCode; } }

else { cout<<" ACS Stream aborted successfully... "<<endl<<endl; } }

// CloseStream(): This function demonstrates the use of acsCloseStream() method // which is used to close an ACS stream. The application will be unable to // request services from the AE Services server after the success of this method. void CloseStream(ACSHandle_t* a_pAcsHandle) {

// acsCloseStream(): Request to close an ACS stream. A confirmation event // will be provided for this method. // @a_pAcsHandle: Handle returned from the acsOpenStream() method // @invokeID: Setting it to zero as Library generated ID is used in this // example. // @privateData: - Presently this parameter is ignored so please pass NULL // in this parameter for acsCloseStream() method

RetCode_t nRetCode = acsCloseStream(*a_pAcsHandle, 0, NULL);

// Checking for the negative response if ( nRetCode < 0)

{ // Vrifying for the ACS handle if(nRetCode == ACSERR_BADHDL)

{ // This error indicates the ACS handle passed in acsCloseStream method

Page 66: Application Initialization using Avaya AE Services TSAPI ... · Application Initialization using Avaya AE Services TSAPI SDK for Windows A Devconnect Tutorial Table of Contents ...

avaya.com

66

// is invalid. Please check valid handle value passed to acsCloseSream // method. The handle could be invalid because the stream associated// with it, is already closed or the TSAPI Client library could not find// the associated stream. In this case the application will not receive // an ACSCloseStreamConfEvent.

cout << " The ACS Handle is invalid" << endl; }

else { cout<< " acsCloseStream() failed with unknown error. " << endl; cout << " Error code: " << nRetCode; } }

else { cout << " ACS Stream close request sent successfully... " << endl; g_nCloseStreamInvokeID = nRetCode; } }

// Notify() method will be called by ESRCallback method whenever it // receive a event notification. This method retrive event from event// queue using acsGetEventBlock() or acsGetEventPoll() methods. The // event information is extracted from event object and processed as // per this application design. Other application should be designed to// include event processing logic as per their needs. void Notify(ACSHandle_t* a_pAcsHandle) {

// A boolean variable which will be true if event is successfully // retrieved otherwise false. bool isEventRetrived = false;

// This hold the size the application will allocate initially to// the event buffer. Keeping the size of event buffer will reduce // applications memory footprint. If this size is set to// a smaller value than the size of any event (say 64), then// application receive an error (i.e. ACSERR_UBUFSMALL). In this // case application should try to retrieve event with a larger// event buffer. Below code demonstrate the implementation for this // scenario. const int APP_DEF_DEFAULT_BUFFER_SIZE = 512;

// CSTA event buffer size unsigned short usEventBufSize = APP_DEF_DEFAULT_BUFFER_SIZE; // A pointer to CSTAEvent_t structure, a pointer is being used// instead of a non-pointer variable as non-pointer variable will // reserve fixed memory space on stack

CSTAEvent_t *cstaEvent = NULL; // Number of events in the Client library queue // Default value assumed 1, we will receive exact value after // acsGetEventBlock() method return. unsigned short usNumEvents = 1;

// We are running a loop here which will run until we successfully// retrieved the event or count of events in the Client library// queue has become zero and size of event buffer has become zero. while(!isEventRetrived || ( usNumEvents > 0 && usEventBufSize > 0) )

{ // To hold the error cause int nError;

// ATT service request private data buffer that store // private data coming with event.

Page 67: Application Initialization using Avaya AE Services TSAPI ... · Application Initialization using Avaya AE Services TSAPI SDK for Windows A Devconnect Tutorial Table of Contents ...

avaya.com

67

ATTPrivateData_t privateData;

// Setting the private data length same as the size of // data field of ATTPrivateData_t structure.

privateData.length = sizeof(privateData.data);

// For the next iterations need to free the memory // before reallocating new memory. if(NULL != cstaEvent)

{ //Free the buffer memory

free(cstaEvent); }

// Reallocate buffer in case any failure detected in// retrieving event earlier.

cstaEvent = (CSTAEvent_t*) malloc((SIZE_T) usEventBufSize);

// To store method return value RetCode_t nRetCode;

// BLOCKING_MODE can be defined in the project settings > C/C++ > // Preprocessor to use acsGetEventBlock() method. If application // wants to use acsGetEventPoll method instead, exclude BLOCKING_MODE // from project setting.

#ifdef BLOCKING_MODE {

// Receiving the events in Blocking mode:// GetEventBlock() method is used to extract the events in the// Blocking mode. In the Blocking mode, the application's calling thread// will be blocked until there is an event from the ACS stream.

// @a_pAsHandle: Handle returned from the acsOpenStream() method. // @cstaEvent: Pointer to an area in the application address// space large enough to hold event that // will be copied by Client library. // @usEventBufSize: Specifies the size of event buffer. // @privateData: Points to a buffer which will receive any private// data that accompanies this event. If the application does not wish // to receive private data, then privateData should be set to 0. // @usNumEvents: Specifies the count of events still pending in Client// library queue to be retrieved on this ACS stream.

nRetCode = acsGetEventBlock(*a_pAcsHandle, (void *)cstaEvent, &usEventBufSize, (PrivateData_t *)&privateData, &usNumEvents );

} #else { // Receiving events in Non-Blocking mode // In the Non-Blocking mode the oldest outstanding event from ACS // stream (whose handle is passed in method call) will be copied into // the applications data space and control will be returned immedietly // to the application.

// If no events are currently queued for the application, the function // will return control immediately to the application with an error code // indicating that no events were available.

//Parameter description same as acsGetEventBlock.

Page 68: Application Initialization using Avaya AE Services TSAPI ... · Application Initialization using Avaya AE Services TSAPI SDK for Windows A Devconnect Tutorial Table of Contents ...

avaya.com

68

nRetCode = acsGetEventPoll(*a_pAcsHandle, (void *)cstaEvent, &usEventBufSize, (PrivateData_t *)&privateData, &usNumEvents); } #endif

if(nRetCode != ACSPOSITIVE_ACK) {

if(nRetCode == ACSERR_BADHDL) { cout<<" The ACS Handle is invalid"<<endl<<endl; } // end of if

else if (nRetCode == ACSERR_UBUFSMALL) { cout<<" Passed event buffer size is smaller than the size of the"

" next available event for this ACS Stream."<<endl<<endl;

// The usEventBufSize variable has been reset by the TSAPI Client// Library to the size of the next message on the ACS// stream. The application should call acsGetEventBlock( )// again with a larger buffer. The ACS event still present// on the Client Library queue.

continue; }// end of else if

else if (nRetCode == ACSERR_NOMESSAGE) {

// The acsGetEventPoll()method return this value to indicate // there were no events available in the Client library queue.

cout << " No events available at this time."; }

else { cout << " acsGetEventBlock()/acsGetEventPoll() failed with"

" unknown error. " << endl; cout << " Error code: " << nRetCode;

break; } }// end of if

else {

// Setting true as we have successfully retrieved event isEventRetrived = true;

// Checking for Confirmation event for the Open Stream request switch(cstaEvent->eventHeader.eventClass)

{ case ACSCONFIRMATION:

{ switch(cstaEvent->eventHeader.eventType)

{ case ACS_OPEN_STREAM_CONF:

{ if(g_nOpenStreamInvokeID ==

cstaEvent->event.acsConfirmation.invokeID) { cout << endl <<" acsOpenStremConfEvent received - Stream"

" opened successfully."<<endl; cout << " API Version: " << cstaEvent->event.acsConfirmation.u.acsopen.apiVer << endl; cout << " Library Version: " <<

Page 69: Application Initialization using Avaya AE Services TSAPI ... · Application Initialization using Avaya AE Services TSAPI SDK for Windows A Devconnect Tutorial Table of Contents ...

avaya.com

69

cstaEvent->event.acsConfirmation.u.acsopen.libVer << endl << endl;

// verify that Private Data is correctly negotiated.

// 1st check the length of the Private Data received if (privateData.length <= 0)

{ // handle error condtion ( abort the Stream ) // return error

cout << endl << " Private Data length is zero"" in acsOpenStreamConf event. Private data" " is not sent as a part of this event.";

// As this application is making use of private// data features, in this condition it is// appropriate to close the application as the // private data is not negotiated successfully. // This could happen if you send a PDV which is // not in range of PDV that AE Services server // supports e.g. "10-25", "0-5", "0", "10" etc

PrintErrorAndExit(a_pAcsHandle);

// If we do not close application and use PD // feature, the request in which we are using // PD feature will fail. In this example,// cstaMonitorDevice method will fail if // we do not close the application at this moment.

}

// 2nd Check the vendor String if ( strcmp(privateData.vendor,ECS_VENDOR_STRING) != 0 )

{ // hanlde error condtion ( abort the Stream ) // return error

}

// 3rd check the One byte descriminator if ( privateData.data[0] != PRIVATE_DATA_ENCODING )

{ // handle error condtion ( abort the Stream ) // return error

} else

{ // Retrieving the Private Data

cout <<" PrivateData = VENDOR: "<< privateData.vendor << endl;

// Checking private data version, whether // it is same as requested or not. char cPDVReturned = privateData.data[1];

// To hold returned PDV as number int nReturnedPDV = atoi(&cPDVReturned);

if(strchr(g_szPrivateDataVersion, '-') == NULL) {

// Requested version is specific i.e. does not contain '-' int nRequestedPDV = atoi(g_szPrivateDataVersion);

if(nRequestedPDV == nReturnedPDV) { cout <<" Private data version negotiation is "

Page 70: Application Initialization using Avaya AE Services TSAPI ... · Application Initialization using Avaya AE Services TSAPI SDK for Windows A Devconnect Tutorial Table of Contents ...

avaya.com

70

"successful."; cout <<" Negotiated private data version is: " << cPDVReturned << endl; }

else { cout <<" Private data version negotiation is failed.";

// This is an error condition where AE Server does // not support the PDV requested.

} }

else {

// A range of PDV is requested

// Make a copy of requested PDV value, this // variable will also store first part of requested PDV // after call to strtok_s. char* szFirst = _strdup(g_szPrivateDataVersion); // To store second part of requested PDV char* szSecond;

// strtok_s method is used to split string// which is of format "m-n". This method // will copy m in szFirst and n in szSecond.

strtok_s(szFirst, "-", &szSecond);

int nMinVersion = atoi(szFirst); int nMaxVersion = atoi(szSecond);

// compare value of m and n with // PDV returned. if(nReturnedPDV >= nMinVersion

&& nReturnedPDV <= nMaxVersion ) { cout <<" Private data version negotiation is " "successful."; cout <<" Negotiated private data version is: " << cPDVReturned << endl; }

else { cout <<" Private data version negotiation is failed.";

// This is an error condition where AE Server does // not support the PDV requested.

} } }

// Sets event object to signaled state. SetEvent(g_hOpenStreamConfEvent); }

else {

// Confirmation event received for some other open// stream request.

cout << " A confirmation event received for an unknown open" " stream request.";

} break;

} case ACS_CLOSE_STREAM_CONF:

{

Page 71: Application Initialization using Avaya AE Services TSAPI ... · Application Initialization using Avaya AE Services TSAPI SDK for Windows A Devconnect Tutorial Table of Contents ...

avaya.com

71

if(g_nCloseStreamInvokeID == cstaEvent->event.acsConfirmation.invokeID) {

// Checking for confirmation event for the Close// Stream request.

// Sets event object to signaled state. SetEvent(g_hCloseStreamConfEvent); }

else {

// Confirmation event received for some other close// stream request.

cout << " A confirmation event received for an unknown close" " stream request.";

}

break; }

case ACS_UNIVERSAL_FAILURE_CONF: {

// Checking for the Failure of Open Stream request nError = cstaEvent->event.acsConfirmation.u.failureEvent.error; cout << " ACS_UNIVERSAL_FAILURE_CONF event received" << endl;

// Verifying error is for open stream that this // application has openedif(g_nOpenStreamInvokeID ==

cstaEvent->event.acsConfirmation.invokeID) {

// Checking for the password of the loginID switch( nError )

{ case tserverBadPasswordOrLogin:

{ cout<<" CTI login password is incorrect"<<endl;

break; }

case tserverNoUserRecord: { cout<<" No user object was found in the security"

" database for the login specified in the" " ACSOpenStream request."<<endl;

break; }

default: { cout << " ACS_UNIVERSAL_FAILURE_CONF event received"

" with unknown error"; cout<<" Error Code: "<<nError; } } }

else if(g_nStartMonitorInvokeID == cstaEvent->event.cstaConfirmation.invokeID) {

// Checking for the password of the loginID switch( nError )

{case tserverDeviceNotSupported:

{ cout<<" Error: Device not supported."<<endl;

break; }

Page 72: Application Initialization using Avaya AE Services TSAPI ... · Application Initialization using Avaya AE Services TSAPI SDK for Windows A Devconnect Tutorial Table of Contents ...

avaya.com

72

default: { cout << " ACS_UNIVERSAL_FAILURE_CONF event received"

" with unknown error"; cout<<" Error Code: "<<nError; } } }

else { cout << " An ACS_UNIVERSAL_FAILURE_CONF event received"

" for an unknown request." << endl; cout<<" Error Code: "<<nError; }

break; }

default: {

// Other application should add more cases as per need. cout << " ACS Confirmation event received" << " with unknown event type." << endl; cout<<" Event Type: "<< cstaEvent->eventHeader.eventType; } } // End of switch

break; } // End of ACSCONFIRMATION case

case CSTACONFIRMATION: {

switch(cstaEvent->eventHeader.eventType) {

case CSTA_MONITOR_CONF: {

// Matching the invokeID received in this event with invokeId // received from invoked cstaMonitorDevice method. if(g_nStartMonitorInvokeID ==

cstaEvent->event.cstaConfirmation.invokeID) {

// Sets event object to signaled state.

SetEvent(g_hMonitorDeviceConfEvent);

g_lMonitorCrossRefID = cstaEvent->event.cstaConfirmation.u. monitorStart.monitorCrossRefID;

cout << endl << " csatMonitorDeviceConfEvent received - " " Monitoring started..." << endl << endl;

} else

{ // Confirmation event received for some other monitor// device request.

cout << " A confirmation event received for an unknown" " monitor device request.";

}

break; }

case CSTA_UNIVERSAL_FAILURE_CONF: {

// Checking for the Failure of Monitor Request nError = cstaEvent->event.cstaConfirmation.u.universalFailure.error; cout << " CSTA_UNIVERSAL_FAILURE_CONF event received." << endl;

Page 73: Application Initialization using Avaya AE Services TSAPI ... · Application Initialization using Avaya AE Services TSAPI SDK for Windows A Devconnect Tutorial Table of Contents ...

avaya.com

73

// Verifying error is for monitor start or stop request if(g_nStartMonitorInvokeID ==

cstaEvent->event.cstaConfirmation.invokeID || g_nStopMonitorInvokeID == cstaEvent->event.cstaConfirmation.invokeID) {

// Checking the cause of the error received// for the monitor request switch(nError)

{ case invalidCstaDeviceIdentifier :

{ cout<<" Error: Invalid Devie Identifier."<<endl;

break; }

case resourceBusy : { cout<<" Error: Resource is busy."<<endl;

break; }

case genericOperationRejection : { cout<<" Error: GENERIC_OPERATION_REJECTION"<<endl;

break; }

default: { cout << " Error: CSTA_UNIVERSAL_FAILURE_CONF event " << " received with unknown error code." << endl; cout << " Error Code: "<< nError; } }// end of inner switch }

else { cout << " Error: CSTA_UNIVERSAL_FAILURE_CONF event " << " received with unknown error code." << endl; cout << " Error Code: "<< nError; }

break; }// end of case

case CSTA_MONITOR_STOP_CONF: {

// Matching the invokeID received in this event with invokeId // received from invoked cstaMonitorDevice method. if(g_nStopMonitorInvokeID ==

cstaEvent->event.cstaConfirmation.invokeID) {

// Sets event object to signaled state. SetEvent(g_hMonitorStopConfEvent); cout<<endl<<" Monitor deactivated successfully... "<<endl; }

else {

// Confirmation event received for some other stop monitor// device request.

cout << " A confirmation event received for an unknown" " stop monitor device request.";

}break;

} default:

{ // Other application should add more cases as per need.

Page 74: Application Initialization using Avaya AE Services TSAPI ... · Application Initialization using Avaya AE Services TSAPI SDK for Windows A Devconnect Tutorial Table of Contents ...

avaya.com

74

cout << " CSTA Confirmation event received" << " with unknown event type." << endl; cout<<" Event Type: "<< cstaEvent->eventHeader.eventType; } }// end of CSTA Confirmation event type switch

break; }// end of CSTACONFIRMATION case

case CSTAUNSOLICITED: {

switch(cstaEvent->eventHeader.eventType) {

case CSTA_SERVICE_INITIATED: { cout << " A Service Initiated event is received. ";

break; }

case CSTA_DELIVERED: {

// Delivered event received

// To store the connection state LocalConnectionState_t connectionState;

connectionState = cstaEvent->event.cstaUnsolicited.u.delivered. localConnectionInfo; CSTAEventCause_t eventCause; // To store the event cause eventCause = cstaEvent->event.cstaUnsolicited.u.delivered.cause;

// check the connection state and cause for the event if( connectionState == csAlerting && eventCause == ecNewCall )

{ cout << " Incoming call detected" << endl;

// Retrieving the information associated with this event long lcallID = cstaEvent->event.cstaUnsolicited.u.delivered.

connection.callID; char* szCallingDeviceID = cstaEvent->event.cstaUnsolicited.u.

delivered.callingDevice.deviceID; char* alertingDevice = cstaEvent->event.cstaUnsolicited.u.

delivered.alertingDevice.deviceID;

cout<<" An incoming Call with CallID "<<lcallID<<" received" <<" from "<<szCallingDeviceID<<" to " <<alertingDevice<< endl;

// check the privateData length if ( privateData.length > 0 )

{ // Event buffer that will contain the decoded private data

// information. ATTEvent_t attEvent;

// Check to ensure that private data is successfully decoded. if(attPrivateData(&privateData, &attEvent)==ACSPOSITIVE_ACK )

{ // check the event type if ( attEvent.eventType == ATT_DELIVERED )

{ // This sample code snippet shows how to // extract UCID information from private data, // other application can choose to extract other private// data information as required.

// extract the Universal Call Identifier (UCID) char* UCID = attEvent.u.deliveredEvent.ucid;

cout << " The UCID is: " << UCID;

Page 75: Application Initialization using Avaya AE Services TSAPI ... · Application Initialization using Avaya AE Services TSAPI SDK for Windows A Devconnect Tutorial Table of Contents ...

avaya.com

75

} // End of if } // End of if

else {

// Decoding Error. cout << " An error occured while decoding"

" private data." << endl; } }// End of outer if

else {

// The event does not contain any private Data. } } // End of if

break; } // End of Case

case CSTA_ESTABLISHED: {

// Extract information included in this event here cout << endl << " A Established event is received. "<< endl;

break; } // End of Case

case CSTA_CONNECTION_CLEARED: {

// Extract information included in this event here cout << endl << " A Connection Cleared event is received. "<< endl;

break; } // End of Case

default: {

// Other application should add more cases as per need. cout << " An event of type CSTAUNSOLICITED is received with"

" unknown event class." << endl; cout<<" Event Type: "<< cstaEvent->eventHeader.eventType; } } // End of switch

break; }// end of CSTACONFIRMATION case

default: { cout << " An event received with unknown event class." << endl; cout<<" Event Class: "<< cstaEvent->eventHeader.eventClass; } }// End of event class switch }// end of else }// end of while loop

if(NULL != cstaEvent) {

//Free the buffer memory free(cstaEvent); } } // end of Notify() method

// This is the callback method that will be called for each advertised// service name. serverName method parameter points to an array// of char which is a null-terminated string representing an// advertised service name or Tlink. // This method returns a boolean value which allow application to // request to stop receiving more service names at any point of time // i.e. if this method returns false, it will not be called further // with other service names. Boolean DisplayServerNames(char* szServiceName, unsigned long lParam) {

Page 76: Application Initialization using Avaya AE Services TSAPI ... · Application Initialization using Avaya AE Services TSAPI SDK for Windows A Devconnect Tutorial Table of Contents ...

avaya.com

76

Boolean bReturnValue = FALSE; if(strcmp(szServiceName, "") != 0)

{ // Service name is printed on console here with a number // assigned to each service name. This application store// service name into map for demonstration. User will be // asked to choose any of the service name later.

cout << endl << ++nServicesCount << ". " << "Service Name: " << szServiceName;

// Making a copy of szServiceName in this application // address space. char *szServiceNameTemp = new char[sizeof(ServerID_t)];

strcpy_s(szServiceNameTemp, sizeof(ServerID_t), szServiceName); // Make an entry in the service name map for later use.

serviceNameMap.insert(serviceNamePair(nServicesCount, szServiceNameTemp));

// Return TRUE so that the callback is called // again with the name of the next advertised // service found.

bReturnValue = TRUE; }

else {

// Method received an empty buffer for service name, // returning false in this scenario will cause stop // receiving any more Service name i.e. this method // will not be called again.

//bReturnValue = FALSE; // Not required as default to FALSE }

return bReturnValue; }// This method uses acsEnumServerNames() TSAPI method to specify// a callback method that will be called for each service name. void EnumerateServiceNames() {

// acsEnumServices(): This TSAPI method is used to enumerate// the names of all servers of a specified stream type. // ST_CSTA: Indicates that CSTA services are to be enumerated. // DisplayServerNames: Call back fuction invoked for each service name.

RetCode_t nRetCode = acsEnumServerNames(ST_CSTA, DisplayServerNames, NULL // user defined variable, value of this

// variable will be passed to the // callback method as lParam parameter.// Passed as NULL here.

);

if ( nRetCode != ACSPOSITIVE_ACK ) {

// some error occurred while sending request. cout<<" Error Code: "<<nRetCode;

// handle error. } }

Code Snippet 23: Sample application code

Page 77: Application Initialization using Avaya AE Services TSAPI ... · Application Initialization using Avaya AE Services TSAPI SDK for Windows A Devconnect Tutorial Table of Contents ...

avaya.com

77

Appendix C: References

1. Avaya MultiVantage® Application Enablement Services TSAPI for Avaya Communication Manager Programmer’s

Reference 02-300544

2. Avaya MultiVantage® Application Enablement Services TSAPI, JTAPI, and CVLAN Client and SDK Installation

Guide 02-300543

3. Avaya MultiVantage® Application Enablement Services Administration and Maintenance Guide, Release 4.1,

02-300357

All documents listed are available for download from the Avaya DevConnect Portal to registered members of the

DevConnect Program. See www.avaya.com/devconnect for information on membership and access to the portal.

Please e-mail any questions or comments pertaining to this tutorial along with the full title name and filename,

located in the lower right corner, directly to the Avaya DevConnect Program at [email protected].

Page 78: Application Initialization using Avaya AE Services TSAPI ... · Application Initialization using Avaya AE Services TSAPI SDK for Windows A Devconnect Tutorial Table of Contents ...

About Avaya

Avaya is a global leader in enterprise communications systems. The company

provides unified communications, contact centers, and related services directly

and through its channel partners to leading businesses and organizations

around the world. Enterprises of all sizes depend on Avaya for state-of-the-art

communications that improve efficiency, collaboration, customer service and

competitiveness. For more information please visit www.avaya.com.

avaya.com

©2009 Avaya Inc. All Rights Reserved. Avaya and the Avaya Logo are trademarks of Avaya Inc. All trademarks identified by ® and ™ are registered trademarks or trademarks, respectively, of Avaya Inc. All other trademarks are the property of their respective owners. The information provided in this tutorial is subject to change without notice. The configurations, technical data, and recommendations provided in this tutorial is believed to be accurate and dependable, but is presented without express or implied warranty. Users are responsible for their application of any products specified in this tutorial.09/09


Recommended