사용자 프로그램과 함수

본 장에서는 X.25 게이트웨이로 사용자 프로그램을 작성하기 위한 방법과 AP를 기술한다.

1. 개요

Tmax의 환경을 설정하여 X25GW를 등록한 후에 X25GW를 사용하기 위해 custom.h, custom.c를 적절히 수정해야 한다. 사용자 프로그램을 수정한 custom.h, custom.c와 X25GW 라이브러리 및 register.c를 링크하여 컴파일하면 X25GW가 완성된다. 이때 생성된 실행 파일명은 Tmax 환경 파일의 SERVER 절에 등록된 이름과 동일해야한다. custom.c에는 여러 가지 사용자 정의 함수가 있는데 각각에 대해서는 각 절의 설명을 참조한다.

2. custom.h

X25GW에서 사용되는 msg_info_t 구조체를 포함하는 파일로서 사용자가 리모트 노드와 X25GW에 통신해야 할 기타 메시지 구조체나 헤더들을 수정할 수 있다. 그러나 msg_info_t 구조체는 X25GW 라이브러리 내부와 사용자 함수가 사용하므로 멤버 변수나 타입, 길이는 수정하면 안 된다. 구조체는 X25GW 라이브러리 내부와 사용자가 수정해야 하는 custom.c 파일의 함수에서 사용된다. custom.c 파일에서는 리모트 노드로부터 메시지를 수신한 직후 불리우는 get_msg_info() 함수에서 이 구조체에 값을 적절히 설정을 해야 한다. 또한 리모트 노드로 메시지를 송신하기 직전에 불리우는 함수인 put_msg_info() 함수에서 이 구조체의 값으로 리모트 노드로 송신한 데이터를 적절히 구성해야 한다.

X25GW에서 사용되는 msg_info_t 구조체는 다음과 같다.

typedef struct msg_info {
    char svc[20];
    int err;
    int len;
    int uid;
    int flags; /* flags를 설정한다. (TPNOREPLY등) */
    int msgtype;
    int channel_id;
    char sys_id[20];  /* 채널 그룹명 */
} msg_info_t;

다음은 msg_info 구조체의 맴버에 대한 설명이다.

멤버 설명

char svc[20]

서비스명을 지정하는 항목으로 리모트 노드에서 서비스를 요청할 때 항목에 서비스명을 주면 TCPGW는 이를 이용하여 서비스를 호출한다.

int err

서비스를 요청하고 응답 데이터를 수신 받았을 경우 에러 유무를 나타내는 항목이다.

int len

송수신 데이터의 길이를 나타내는 항목이다.

int uid

동기 통신할 경우 TCPGW가 만든 UID를 담고있는 항목이다.

int flags

리모트 노드에서 Tmax로 서비스를 요청할 때 사용하는 항목이다.

  • NOFLAGS : 리모트 노드에서 요청한 서비스에 대해서 응답을 받는 경우

  • TPNOREPLY : 리모트 노드에서 요청한 서비스에 대해서 응답을 받지 않고 서비스 요청만 하는 경우(Tmax의 tpacall에 TPNOREPLY와 같다.)

int msgtype

미사용 항목이다.

char sys_id[20]

송수신 채널 번호이다.

3. custom.c

custom.c는 개발자가 리모트 노드와 X25GW가 통신하기 위해 구현해야 하는 것으로 X25GW 라이브러리(libx25gw.a, libx25gw.so)와 함께 컴파일해서 사용해야 한다. 함수들의 사용 예제는 사용자 프로그램과 함수에서 설명한다.

다음은 custom.c에서 구현해야 하는 함수 목록이다.

함수 설명

init_remote_info

리모트 노드와 연결을 맺기에 전에 호출되는 함수이다.

remote_connected

리모트 노드와 연결을 맺은 후에 호출되는 함수이다.

remote_closed

리모트 노드와 연결을 종료한 후 호출되는 함수이다.

get_msg_info

리모트 노드로부터 요청이나 응답이 도착하여 데이터를 읽은 후 TCP/IP 게이트웨이 라이브러리와 custom.c와의 인터페이스 역할을 하는 info를 참조 또는 가공하는 함수이다.

get_channel_num

Tmax 서비스나 클라이언트로부터 요청한 데이터를 리모트 노드에 전송할 때 사용자가 채널을 선택할 수 있도록 하는 함수이다.

put_msg_info

리모트 노드로 메시지를 전송하고자 할 때 호출되는 함수이다.

get_service_name3

tpreply()나 tpacall()을 할 서비스 이름의 오류 코드에 따라서 설정하는 함수이다.

prepare_shutdown

TCPGW가 종료하기 직전에 call되는 함수이다.

inmsg_recovery

리모트 노드로부터 요청을 tpacall(…​, TPBLOCK)로 처리 중 에러가 발생하는 경우 호출되는 함수이다.

outmsg_recovery

리모트 노드로 요청을 보낼 때 오류가 발생할 경우 호출된다.

3.1. init_remote_info

리모트 노드와 연결을 맺기에 전에 호출된다. X25GW가 자신의 초기화 작업을 마친 후에 곧바로 호출되는 함수로 한번만 호출된다. Tmax 환경 파일의 CLOPT에 [–k] 옵션으로 공유 메모리 키를 설정한 경우 연결에 대한 정보 등을 저장하기 위해 공유 메모리를 생성하는 로직이 구현할 수 있다. 경우에 따라 내부 로직을 구현하지 않아도 된다.

  • 프로토타입

    int init_remote_info (char *myname, int mynumber, int num_channel, int key)
  • 파라미터

    파라미터 설명

    myname

    X25GW 서버명이다.

    mynumber

    같은 X25GW가 동시에 여러 개 실행될 경우에 각각의 프로세스를 구분할 수 있는 X25GW 프로세스 번호로 0부터 시작한다.

    num_channel

    X25GW가 연결하고 있는 max 채널 수로 환경 파일에 정의한 채널의 합이다.

    key

    Tmax 환경 파일에서 [–k] 옵션으로 설정한 공유 메모리 키 값이다.

3.2. remote_connected

리모트 노드와 연결을 맺은 후 호출되는 함수로 리모트 노드와 연결을 맺은 후 해야 할 작업을 수행한다. 함수는 채널 수만큼 호출된다. 또한 도중에 채널이 해제되었다가 다시 연결될 때도 호출된다.

  • 프로토타입

    int remote_connected(int index, int linkno, int lcnno, int type)
  • 파라미터

    파라미터 설명

    index

    X25GW가 연결하고 있는 각각의 채널에 대한 자신의 index 값이다.

    linkno

    연결된 채널의 링크 번호이다.

    lcnno

    연결된 채널의 번호로 하나의 링크에 여러 개의 lcn이 있다. 일반적으로 Logical한 번호라고 인식하면 된다.

    type

    리모트 노드와 연결된 채널 타입으로 IN_CHANNEL 또는 OUT_CHANNEL을 설정한다.

3.3. remote_closed

리모트 노드와 연결을 종료한 후 호출되는 함수이다. 리모트 노드와 연결이 끊어진 후에 해야할 작업이 있다면 하도록 한다. init_remote_info 함수에서 공유 메모리를 생성하는 로직을 구현한 경우 해제하는 작업 로직을 구현한다. 채널 수만큼 호출된다.

  • 프로토타입

    int remote_closed(int index, int type)
  • 파라미터

    파라미터 설명

    index

    각각의 채널에 대한 자신의 index값이다.

    type

    리모트 노드와 연결된 채널 타입으로 IN_CHANNEL 또는 OUT_CHANNEL을 설정한다.

3.4. get_msg_info

리모트 노드으로부터 요청이나 응답이 도착하여 데이터를 읽은 후 데이터를 Tmax 서비스 프로그램으로 다시 요청이나 응답을 전송하기 전에 해당 데이터 값을 가공하거나, 정보 전송을 위한 여러 정보(uid, len, flags, service명 등)들을 X25 게이트웨이 라이브러리와 custom.c와의 인터페이스 역할을 하는 info를 참조, 또는 가공하는 함수이다.

  • 프로토타입

    int get_msg_info(char *data,msg_info_t *info)
  • 파라미터

    파라미터 설명

    data

    리모트 노드로부터 읽은 데이터 부분이다.

    info

    X.25 게이트웨이 라이브러리(libx25gw.a, libx25gw.so)와 custom.c와 인터페이스 역할을 하는 구조체 구조이다. 사용자가 수신 받은 데이터를 기초로 해서 info 구조체의 항목에 각종 정보를 함수에서 설정한다.

  • 반환값

    Tmax 서비스로 보낼 type을 정의한다. X25GW는 이 값을 바탕으로 Tmax로 어떤 처리를 할 것인지를 판단한다.

    예를 들어 REMOTE_REQUEST는 리모트 노드로부터 Request가 발생한 것으로 판단하며, REMOTE_REPLY는 Tmax 서비스로부터 Request가 발생하여 리모트 노드로부터 Response가 오는 경우 반환하는 값이다. 리모트 노드로부터 응답을 수신한 경우에는 반드시 UID 값을 info 구조체의 uid 항목에 지정해 주어야 한다. 그리고 기타 다른 값들도 상황에 맞게 주어야 한다.

3.5. get_channel_num

Tmax 서비스나 클라이언트로부터 요청한 데이터를 리모트 노드에 전송할 때 사용자가 채널을 선택할 수 있도록 한다. 사용자는 주어진 데이터의 특성에 따라서 전송할 채널을 지정할 수 있다. 여기서 지정하는 것은 리모트 노드와 연결된 소켓 번호가 아니라 단순한 채널 번호이다. X25GW는 사용자가 지정한 채널을 사용할 수 없으면 오류를 반환한다.

  • 프로토타입

    int get_channel_num(char *data)
  • 파라미터

    파라미터 설명

    data

    리모트 노드로 보내기 위한 데이터이다.

  • 반환값

    채널 번호를 반환한다.

3.6. put_msg_info

리모트 노드로 메시지를 전송하고자 할 때 호출한다. 동기형 통신인 경우에는 사용자가 이 함수에서 UID를 메시지에 저장해야 한다. UID는 info 구조체의 uid 항목의 값을 사용해도 되고, 또는 사용자가 임의의 UID를 만들어서 사용한 후에 info의 uid 항목에 넣어주면 된다.

  • 프로토타입

    int put_msg_info(char *data, msg_info_t *info)
  • 파라미터

    파라미터 설명

    data

    리모트 노드로 보낼 데이터이다.

    info

    리모트 노드로 보낼 데이터의 정보이다.

  • 반환값

    실제적으로 리모트 노드에 전송할 데이터의 전체 길이를 반환해야 한다. 메시지 헤더와 실 데이터를 더한 길이를 반한한다.

3.7. get_service_name3

Tmax에서 리모트 노드로 요청을 보낼 때 요청을 보내는 서버와 결과를 받는 서버를 달리하는 NON 블록형이나 비동기형 X25GW를 구성하는 경우 tpreply()나 tpacall()을 할 서비스의 이름을 오류 코드에 따라서 설정한다.

  • 프로토타입

    int get_service_name(char *header, int err, char *svc)
  • 파라미터

    파라미터 설명

    header

    [-H], [-h] 옵션으로 설정한 X25GW에서 저장하고 있는 사용자 헤더의 포인터이다.

    err

    오류 코드이다.

    svc

    tpreply()나 tpacall()를 받는 서비스의 이름을 설정한다.

3.8. prepare_shutdown

X25GW가 종료하기 직전에 call되는 함수로써, 일반적으로 init_remote_info() 함수에서 생성한 공유 메모리를 해제하는 일 등을 한다.

  • 프로토타입

    int prepare_shutdown(int code)
  • 파라미터

    파라미터 설명

    code

    shutdown code로 현재는 사용되지 않는다.

3.9. inmsg_recovery

리모트 노드로부터 요청을 tpacall(…​, TPBLOCK)로 처리했을 경우 서버가 실행되어 있지 않으면 에러가 돌아오게 되는데, 이러한 때에 호출된다. 사용자는 함수 내에서 적당히 새로운 데이터를 만들고 데이터의 크기를 반환한다.

  • 프로토타입

    int inmsg_recovery(char *data, msg_info_t *info)
  • 파라미터

    파라미터 설명

    data

    리모트 노드로부터 읽은 데이터 부분이다.

    info

    리모트 노드로부터 읽은 데이터의 정보이다.

    의미있는 값은 다음과 같다.

    • info→svc : tpacall()했었던 서비스 이름

    • info→len : tpacall()한 데이터 길이

    • info→err : 에러가 발생하는 경우 tperrno

    • info→uid : 이전 get_msg_info()시에 생성되었던 UID 값

  • 반환값

    사용자는 함수에서 새로운 데이터의 길이를 반환해야 한다.

    데이터의 길이가 0 보다 클 경우 info→svc에 값이 존재하면 해당 서비스로 tpacall(…​, TPNOREPLY)하고, 그 외에는 리모트 노드로 응답을 보낸다. 데이터의 길이가 음수일 경우 데이터를 버린다.

3.10. outmsg_recovery

리모트 노드로 요청을 보낼 때 에러가 발생할 경우 호출된다. 사용자는 함수 내에서 적당히 새로운 데이터를 만들고 원하는 서비스 이름 및 UID 등을 설정하고 데이터의 크기를 반환한다.

  • 프로토타입

    int outmsg_recovery(char *data, msg_info_t *info)
  • 파라미터

    파라미터 설명

    data

    리모트 노드로 보낼 데이터이다.

    info

    리모트 노드로 보낼 데이터의 정보이다.

    의미있는 값은 다음과 같다.

    • info→len : 데이터 길이

    • info→uid : X25GW가 임의로 생성한 UID 값

    • info→msgtype: - 1000 이상이면 외부로 응답을 보내다 에러 발생, - 1000 미만이면 외부로 요청을 보내다 에러 발생

    • info→err : TPECLOSE이면 응답을 기다리다 채널이 끊어진 경우 그 외에는 요청을 보내려다 에러가 발생한 경우

  • 반환값

    사용자는 새로운 데이터의 길이를 반환해야한다.

    데이터의 길이가 0 보다 클 경우 info→svc에 값이 존재하면 해당 서비스로 tpacall(…​, TPNOREPLY)하고, 그 외에는 info→msgtype이 1000 이상이면 데이터를 버리고 info→msgtype이 1000 미만이면 데이터를 call한 쪽으로 되돌려 준다.

4. register.c

사용자 함수 등록 파일로서, 사용자가 등록한 함수들만 게이트웨이 라이브러리에서 호출된다. 게이트웨이를 컴파일할 때 반드시 register.c를 포함시켜야 한다. 사용하지 않는 함수는 NULL을 등록한다.

다음은 register.c 예제이다.

#include <stdio.h>
#include "custom.h"

extern int init_remote_info(char *name, int index, int n, int key);
extern int prepare_shutdown();
#ifdef _NCR_X25
extern int remote_connected(int index, int pcid, char *lname, char *rname, int type);
#else
extern int remote_connected(int index, int linkno, int lcnno, int type);
#endif
extern int remote_closed(int index, int type);
extern int get_msg_info(char *data, msg_info_t *info);
extern int put_msg_info(char *data, msg_info_t *info);
extern int get_service_name(char *header, int err, char *svc);
extern int get_channel_num(char *data);
extern int inmsg_recovery(char *data, msg_info_t *info);
extern int outmsg_recovery(char *data, msg_info_t *info);

/***************************************************************
 *  int
 *  _register_custom()
 *
 *      returns no used
 *      [function number]
 *        1.  init_remote_info
 *        2.  prepare_shutdown
 *        3.  remote_connected
 *        4.  remote_closed
 *        5.  get_msg_info
 *        6.  put_msg_info
 *        7.  get_service_name
 *        8.  get_channel_num
 *        9.  inmsg_recovery
 *        10. outmsg_recovery
 ***************************************************************/
int
_register_custom()
{
        _x25gw_regfn(1,  init_remote_info);
        _x25gw_regfn(2,  prepare_shutdown);
        _x25gw_regfn(3,  remote_connected);
        _x25gw_regfn(4,  remote_closed);
        _x25gw_regfn(5,  get_msg_info);
        _x25gw_regfn(6,  put_msg_info);
        _x25gw_regfn(7,  get_service_name);
        _x25gw_regfn(8,  get_channel_num);
        _x25gw_regfn(9,  NULL);
        _x25gw_regfn(10, NULL);

        return 1;
}