내용 목차
본 장에서는 TCP/IP 게이트웨이를 사용하기 위해 custom.h, custom.c, regidster.c를 수정하는 방법에 대해 설명한다.
Tmax의 환경을 설정하여 TCPGW를 등록한 후에 TCPGW를 사용하기 위해 custom.h, custom.c를 수정해야 한다.
custom.h에서 msg_header_t 구조체를 TCPGW를 사용하고자 하는 목적에 맞게 수정해야 한다.
TCP/IP는 데이터의 끝을 알수가 없으므로 데이터 수신의 종료 시점 또한 알 수 없기 때문에 가변 길이의 데이터를 처리하기가 곤란하다. 그래서 TCPGW는 msg_header_t 구조체를 사용하여 리모트 노드와 메시지 헤더를 설정하여 실 데이터의 길이를 구할 수 있는 구조로 되어 있다. 구조체의 정보는 TCPGW와 리모트 노드 사이에 메시지 헤더를 지정하는 구조체이므로 해당 리모트 노드와 통신할 때 사용하는 메시지 헤더를 등록해준다.
TCPGW는 리모트 노드로부터 데이터를 수신할 때 먼저 msg_header_t의 길이만큼 데이터를 수신받고 msg_header_t의 구조체에서 실 데이터의 길이를 얻은 후에 실 데이터를 수신받는다. msg_header_t는 정확하게 등록해야만 둘 사이의 통신이 원활히 이루어 진다.
사용자가 정의한 msg_header_t의 정보는 TCPGW와 리모트 노드의 통신에서만 사용하고 서비스 호출할 때는 전달되지 않는다.
custom.h를 수정한 이후에는 custom.c를 적절하게 수정해야 한다. custom.c에는 여러 가지 사용자 정의 함수가 있는데, 각각에 대해서는 “3.3. custom.c”에서 자세히 설명한다.
수정한 custom.h, custom.c와 TCPGW 라이브러리 및 register.c를 링크하여 컴파일하면 TCPGW가 완성된다.
이때 생성된 실행 파일명은 Tmax 환경 파일의 SERVER 절에 등록된 이름과 동일해야 한다.
custom.h는 TCPGW에서 사용되는 msg_info_t 구조체를 포함하는 파일로, 사용자가 리모트 노드와 TCPGW 간에 통신해야 할 기타 메시지 구조체나 헤더들을 수정할 수 있다.
msg_info_t 구조체는 TCPGW 라이브러리 내부와 사용자 함수 사이에 사용하므로 멤버 변수나 타입, 길이 등을 수정하면 안 된다.
TCPGW 라이브러리 내부와 사용자가 수정해야 하는 custom.c 파일의 함수에서 사용되는 구조체이다. custom.c 파일에서는 리모트 노드로부터 메시지를 수신한 직후 불리우는 get_msg_info() 함수에서 이 구조체에 값을 적절히 설정을 해야 한다.
또한 리모트 노드로 메시지를 송신하기 직전에 불리우는 함수인 put_msg_info() 함수에서 구조체의 값으로 리모트 노드로 송신한 데이터를 구성해야 한다. get_msg_info()와 put_msg_info()의 수정사항에 대한 좀 더 자세한 내용은 “3.3. custom.c”를 참고한다.
TCPGW에서 사용되는 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; } msg_info_t;
다음은 msg_info 구조체의 맴버에 대한 설명이다.
멤버 | 설명 |
---|---|
char svc[20] | 서비스명을 지정하는 항목이다. 리모트 노드에서 서비스를 요청할 때 항목에 서비스명을 주면 TCPGW는 이를 이용하여 서비스를 호출한다. |
int err | 서비스를 요청하고 응답 데이터를 수신받았을 경우 에러 유무를 나타내는 항목이다. |
int len | 송수신 데이터의 길이를 나타내는 항목이다. |
int uid | 동기 통신할 경우 TCPGW가 생성한 UID를 담고 있는 항목이다. |
int flags | 리모트 노드에서 Tmax로 서비스를 요청할 때 사용하는 항목이다.
|
int msgtype | 현재 사용하지 않는다. |
int channel_id | 송수신 채널 번호이다. |
custom.c는 개발자가 리모트 노드와 TCPGW가 통신하기 위해 구현해야 하는 것으로, TCPGW 라이브러리(libtcpgw.a, libtcpgw.so)와 함께 컴파일해서 사용해야 한다. custom.c는 정의된 형식에 맞게 구현해야 하며 그 형식은 다음과 같다.
변수
custom.c에는 다음과 같은 변수를 정의해야 한다.
msg_header_size
라이브러리 내부에서 사용자가 정의한 메시지 헤더의 사이즈로 인식되어 사용되는 변수이다. 따라서 이 변수는 다음의 사용법처럼 사용자 정의 메시지 헤더 사이즈로 설정해 주어야 한다.
int msg_header_size = sizeof(msg_header_t);
comm_header_size
msg_header_size가 0으로 설정된 경우 이 변수가 msg_header_size와 같은 용도로 사용된다. msg_header_size 변수와 함께 정의된 경우는 msg_header_size 값을 사용하게된다.
int comm_header_size = 0;
함수
다음은 custom.c에서 구현해야 하는 함수 목록이다.
함수 | 설명 |
---|---|
init_remote_info | 리모트 노드와 연결을 맺기에 전에 호출되는 함수이다. |
remote_connected | 리모트 노드와 연결을 맺은 후에 호출되는 함수이다. |
remote_connected_ipv6 | IPv6 프로토콜 환경에서 리모트 노드와 연결을 맺은 후에 호출되는 함수이다. |
remote_closed | 리모트 노드와 연결을 종료한 후 호출되는 함수이다. |
allow_connection | 리모트 노드와 새로운 연결이 맺어지기 전에 호출되는 함수이다. 해당 연결 요청의 허용 여부를 반환값으로 결정할 수 있다. |
allow_connection_ipv6 | IPv6 프로토콜 환경에서 리모트 노드와 새로운 연결이 맺어지기 전에 호출되는 함수이다. 해당 연결 요청의 허용 여부를 반환값으로 결정할 수 있다. |
get_msg_length | 리모트 노드로부터 요청이나 응답이 도착하는 경우 호출하는 함수로 반환된 값만큼, 실 데이터를 다시 read하는 함수이다. |
get_msg_info | 리모트 노드으로부터 요청이나 응답이 도착하여 데이터를 읽은 후 TCPGW 라이브러리와 custom.c와의 인터페이스 역할을 하는 info를 참조 또는 가공하는 함수이다. |
get_channel_num | Tmax 서비스나 클라이언트로부터 요청한 데이터를 리모트 노드에 전송할 때 사용자가 채널을 선택할 수 있도록 하는 함수이다. |
put_msg_info | 리모트 노드로 메시지를 전송하고자 할 때 호출되는 함수이다. |
put_msg_complete | 리모트 노드로 메시지를 전송한 후에 호출되는 함수이다. |
get_service_name | tpreply()나 tpacall()을 할 서비스명의 오류 코드에 따라서 설정하는 함수이다. |
prepare_shutdown | TCPGW가 종료하기 직전에 call되는 함수이다. |
set_service_timeout | 서비스 타임아웃이 발생할 경우 사용자가 호출할 수 있는 함수이다. |
chk_end_msg | 리모트 노드로부터 데이터를 수신할 때 데이터의 끝을 나타내는 특정 문자 혹은 비트 스트림이 존재할 경우 사용자가 호출할 수 있는 함수이다. |
inmsg_recovery | 리모트 노드로부터의 요청을 처리했을 때 오류가 발생하는 경우 호출하는 함수이다. |
outmsg_recovery | 리모트 노드로 요청을 보낼 때 오류가 발생할 경우 호출된다. |
get_extmsg_info | get_msg_info와 일부 기능을 제외하고 기본적으로 동일한 기능을 갖는다. |
put_extmsg_info | put_msg_info와 일부 기능을 제외하고 기본적으로 동일한 기능을 갖는다. |
set_ping_msg | 채널 장애 감시를 위해서 보낼 메시지 설정 및 주기, 타임아웃 등을 설정할 수 있는 사용자 함수이다. |
chk_pong_msg | 채널 장애 감시 응답 메시지 여부를 체크하는 사용자 함수이다. |
set_extping_msg | 서버에 채널 장애를 감지할 때 보낼 메시지를 설정하는 함수이다. |
chk_extpong_msg | 채널 장애를 감지할 때 서버로부터 받은 메시지를 확인하는 함수이다. |
reset_ping_msg | TCP/IP Ping(채널 장애 감지) 메시지의 전송 여부와 전송 메시지를 재설정하기 위해 주기적으로 호출되는 함수이다. |
reset_extping_msg | reset_ping_msg와 일부 기능을 제외하고 기본적으로 동일한 기능을 갖는다. |
set_error_msg | 리모트 노드와의 거래 중 에러가 발생한 경우 자동으로 호출되는 함수이다. |
get_msg_security | get_msg_info 호출된 이후에 데이터를 가공할 수 있는 함수이다. |
put_msg_security | put_msg_info 호출되기 전에 데이터를 가공할 수 있는 함수이다. |
본 절에서 설명한 함수들의 사용 예제는“제4장 예제”에서 설명한다.
리모트 노드와 연결을 맺기 전에 호출되는 함수이다. TCPGW가 자신의 초기화 작업을 종료한 후 즉시 호출되는 함수이며 한 번만 호출된다. Tmax 환경 파일의 CLOPT에 [–k ] 옵션으로 공유 메모리 키를 설정한 경우 연결에 대한 정보 등을 저장하기 위해 공유 메모리를 생성하는 로직을 구현할 수 있다. 경우에 따라 내부 로직을 구현하지 않아도 된다.
사용법
int init_remote_info(char *myname, int mynumber, int num_channel, int key)
파라미터
파라미터 | 설명 |
---|---|
myname | TCPGW 서버명이다. |
mynumber | 같은 TCPGW가 동시에 여러 개 실행될 경우에 각각의 프로세스를 구분할 수 있는 TCPGW 프로세스 번호로, 0부터 시작한다. |
num_channel | TCPGW가 연결하고 있는 max 채널 수이다. Tmax 환경 파일에 [-n], [-N ]옵션으로 설정한 값의 합이다. |
key | Tmax 환경 파일에서 [–k ] 옵션으로 설정한 공유 메모리 키 값이다. |
리모트 노드와 연결을 맺은 후 호출되는 함수로, 리모트 노드와 연결을 맺은 후 해야 할 작업이 있다면 함수에서 하도록 한다. 함수는 채널 수만큼 호출되고 도중에 채널이 해제되었다가 다시 연결될 때도 호출된다.
사용법
int remote_connected(int index, int addr, int portno, int type, int fd)
파라미터
파라미터 | 설명 |
---|---|
index | TCPGW가 [-n] 또는 [-N] 옵션으로 여러 개의 채널을 연결하고 있는 경우 각각의 채널에 대한 자신의 index 값이다. |
addr | 리모트 노드의 주소이다. |
portno | 연결된 서버의 포트 번호이다. TCPGW가 클라이언트 모드로 동작한다면 리모트 노드의 포트 번호이고, TCPGW가 서버 모드로 동작한다면 Listen하고 있는 소켓의 포트 번호이다. |
type | 리모트 노드와 연결된 채널 타입이다. IN_CHANNEL 또는 OUT_CHANNEL인지를 나타낸다. |
fd | 리모트 노드와 연결된 소켓 번호이다. |
IPv6 프로토콜 환경에서 리모트 노드와 연결을 맺은 후 호출되는 함수로 리모트 노드와 연결을 맺은 후 해야 할 작업이 있다면 함수에서 하도록 한다. 함수는 채널 수만큼 호출되고 도중에 채널이 해제되었다가 다시 연결될 때도 호출된다.
IPv6 환경에서는 반드시 remote_connected Callback 함수가 아닌 remote_connected_ipv6 Callback 함수를 설정해야 한다. 이 Callback 함수를 설정하지 않고 IPv6 환경에서 사용할 경우에는 remote_connected 함수가 호출되지만 ipaddr 값에 임의의 값이 설정되며 slog에 Warning 메시지가 기록된다.
사용법
#include <arpa/inet.h> int remote_connected_ipv6(int index, struct sockaddr *saddr, int portno, int type, int fd)
파라미터
파라미터 | 설명 |
---|---|
index | TCPGW가 [-n] 또는 [-N] 옵션으로 여러 개의 채널을 연결하고 있는 경우 각각의 채널에 대한 자신의 index 값이다. |
saddr | 리모트 노드의 주소 및 포트 번호가 저장되어 있다. IPv4 또는 IPv6 프로토콜 환경에 적합한 sockaddr 구조체 타입으로 캐스팅하여 사용한다. |
portno | 연결된 서버의 포트 번호이다. TCPGW가 클라이언트 모드로 동작한다면 리모트 노드의 포트 번호이고, TCPGW가 서버 모드로 동작한다면 Listen하고 있는 소켓의 포트 번호이다. |
type | 리모트 노드와 연결된 채널 타입이다. IN_CHANNEL 또는 OUT_CHANNEL인지를 나타낸다. |
fd | 리모트 노드와 연결된 소켓 번호이다. |
예제
int remote_connected_ipv6(int index, struct sockaddr *saddr, int portno, int type, int fd) { char buf[INET6_ADDRSTRLEN]; char *ipaddr = NULL; int cli_portno; if (index < 0) return -1; if (saddr->sa_family == AF_INET6) { ipaddr = (char *)inet_ntop(AF_INET6, &(((struct sockaddr_in6 *)saddr)->sin6_addr), buf, sizeof(buf)); cli_portno = ntohs(((struct sockaddr_in6 *)saddr)->sin6_port); } else if (saddr->sa_family == AF_INET) { ipaddr = (char *)inet_ntop(AF_INET, &(((struct sockaddr_in *)saddr)->sin_addr), buf, sizeof(buf)); cli_portno = ntohs(((struct sockaddr_in *)saddr)->sin_port); } if (ipaddr == NULL) ipaddr = "unknown"; printf("remote_connected_ipv6, REMOTE[%d] IPADDR[%s] CLIPORT[%d] SVRPORT[%d] TYPE[%d] fd[%d] connected\n", index, ipaddr, cli_portno, portno, type, fd); return 1; }
리모트 노드와 연결을 종료한 후 호출되는 함수로, 리모트 노드와 연결이 끊어진 후에 해야 할 작업이 있다면 함수에서 한다. init_remote_info 함수에서 공유 메모리를 생성하는 로직을 구현한 경우 이 함수에서 해제하는 작업 로직을 구현한다. 채널 수만큼 호출된다.
사용법
int remote_closed(int index, int type)
파라미터
파라미터 | 설명 |
---|---|
index | TCPGW가 [-n] 또는 [ -N] 옵션으로 여러 개의 채널을 연결하고 있는 경우 각각의 채널에 대한 자신의 index 값이다. |
type | 리모트 노드와 연결된 채널 타입이다. IN_CHANNEL 또는 OUT_CHANNEL인지를 나타낸다. |
TCPGW로 리모트 노드가 연결을 시도하거나 또는 TCPGW가 리모트 노드로 연결을 시도해서 연결이 성공했을 때 remote_connected() Callback 함수가 호출되기 전에 호출된다. 해당 리모트와의 연결을 허용할 것인지 결정할 수 있다.
사용법
int allow_connection(int addr, int portno, int type, int fd)
파라미터
파라미터 | 설명 |
---|---|
addr | 리모트 노드의 주소이다. |
portno | 연결된 서버의 포트 번호이다. TCPGW가 클라이언트 모드로 동작한다면 리모트 노드의 포트 번호이고, TCPGW가 서버 모드로 동작한다면 Listen하고 있는 소켓의 포트 번호이다. |
type | 리모트 노드와 연결된 채널 타입이다. IN_CHANNEL 또는 OUT_CHANNEL인지를 나타낸다. |
fd | 리모트 노드와 연결된 소켓 번호이다. |
반환값
반환값 | 설명 |
---|---|
1 | 해당 리모트 노드와의 연결 요청을 허용한다. |
음수 | 해당 리모트 노드와의 연결을 허용하지 않는다. |
예제
int allow_connection(int addr, int portno, int type, int fd) { int i, n, len; struct in_addr in; char *ipaddr, *endptr; char *deny[] = {"10.10.30.1", "121.100.100.*", NULL}; if (addr == -1) return -1; in.s_addr = addr; ipaddr = inet_ntoa(in); for (i = 0; deny[i] != NULL; i++) { if ((endptr = strpbrk(deny[i], "*")) != NULL) { if (strncmp(deny[i], ipaddr, (endptr - deny[i])) == 0) return -1; } else { if (strcmp(deny[i], ipaddr) == 0) return -1; } } return 1; }
IPv6 프로토콜 환경에서 TCPGW로 리모트 노드가 연결을 시도하거나 또는 TCPGW가 리모트 노드로 연결을 시도해서 연결이 성공했을 때 remote_connected() Callback 함수가 호출되기 전에 호출된다. 해당 리모트와의 연결을 허용할 것인지 결정할 수 있다.
IPv6 환경에서는 반드시 allow_connection Callback 함수가 아닌 allow_connection_ipv6 Callback 함수를 설정해야 한다. 이 Callback 함수를 설정하지 않고 IPv6 환경에서 사용할 경우에는 allow_connection 함수가 호출되지만 ipaddr 값에 임의의 값이 설정되며 slog에 Warning 메시지가 기록된다.
사용법
#include <arpa/inet.h> int allow_connection(struct sockaddr *saddr, int portno, int type, int fd)
파라미터
파라미터 | 설명 |
---|---|
saddr | 리모트 노드의 주소 및 포트 번호이다. IPv4 또는 IPv6 프로토콜 환경에 적합한 sockaddr 구조체 타입으로 캐스팅하여 사용한다. |
portno | 연결된 서버의 포트 번호이다. TCPGW가 클라이언트 모드로 동작한다면 리모트 노드의 포트 번호이고, TCPGW가 서버 모드로 동작한다면 Listen하고 있는 소켓의 포트 번호이다. |
type | 리모트 노드와 연결된 채널 타입이다. IN_CHANNEL 또는 OUT_CHANNEL인지를 나타낸다. |
fd | 리모트 노드와 연결된 소켓 번호이다. |
반환값
반환값 | 설명 |
---|---|
1 | 해당 리모트 노드와의 연결 요청을 허용한다. |
음수 | 해당 리모트 노드와의 연결을 허용하지 않는다. |
예제
int allow_connection_ipv6(struct sockaddr *saddr, int svr_portno, int type, int fd) { char buf[INET6_ADDRSTRLEN]; char *ipaddr; int cli_portno; int i, n, len; char *endptr; char *allow[] = {"10.10.30.1", "121.100.100.*", NULL}; if (saddr->sa_family == AF_INET6) { ipaddr = (char *)inet_ntop(AF_INET6, &(((struct sockaddr_in6 *)saddr)->sin6_addr), buf, sizeof(buf)); cli_portno = ntohs(((struct sockaddr_in6 *)saddr)->sin6_port); } else if (saddr->sa_family == AF_INET) { ipaddr = (char *)inet_ntop(AF_INET, &(((struct sockaddr_in *)saddr)->sin_addr), buf, sizeof(buf)); cli_portno = ntohs(((struct sockaddr_in *)saddr)->sin_port); } if (ipaddr == NULL) ipaddr = "unknown"; for (i = 0; allow[i] != NULL; i++) { if ((endptr = strpbrk(allow[i], "*")) != NULL) { if (strncmp(allow[i], ipaddr, (endptr - deny[i])) == 0) return 1; } else { if (strcmp(allow[i], ipaddr) == 0) return 1; } } return -1; }
리모트 노드로부터 요청이나 응답이 도착하여, 해당 채널에서 msg_header_t 부분만을 recv(msg_header_size 또는 comm_header_size에서 지정한 값만큼을 읽는다)한 후 호출하는 함수로 반환된 값만큼, 실 데이터를 다시 read하게 된다.
사용법
int get_msg_length(msg_header_t *hp)
파라미터
파라미터 | 설명 |
---|---|
hp | 개발자가 custom.h에 정의할 수 있는 msg_header_t 구조체의 포인터이다. 일반적으로 해당 채널로부터 데이터를 읽는 경우 정해진 헤더의 크기만큼 데이터를 읽은 후에 헤더에 설정되어 있는 데이터 길이값을 얻어서 이를 바탕으로 다음 실 데이터를 읽을 수 있도록 되어 있다. hp는 TCPGW가 리모트 노드로부터 읽은 헤더 데이터를 넘겨준다. |
반환값
리모트 노드로부터 실 데이터의 길이를 반환한다. 함수의 반환값으로 TCPGW는 실 데이터를 리모트 노드에서 읽게 된다.
헤더를 확인하고 문제가 있을 경우에 -2를 리턴하면 해당 채널이 종료된다.
리모트 노드으로부터 요청이나 응답이 도착하여 데이터를 읽은 후 데이터를 Tmax 서비스 프로그램으로 다시 요청이나 응답를 전송하기 전에 해당 데이터 값을 가공하거나, 정보 전송을 위한 여러 정보(uid, len, flags, 서비스명 등)들을 TCPGW 라이브러리와 custom.c와의 인터페이스 역할을 하는 info를 참조 또는 가공하는 함수이다.
사용법
int get_msg_info(msg_header_t *hp, char *data,msg_info_t *info)
파라미터
파라미터 | 설명 |
---|---|
hp | 리모트 노드로부터 읽어온 메시지 헤더 데이터 대한 포인터이다. get_msg_length에서 사용한 구조체와 동일하다. |
data | 리모트 노드로부터 읽은 데이터 부분이다. |
info | TCPGW 라이브러리(libtcpgw.a, libtcpgw.so)와 custom.c와 인터페이스 역할을 해주는 구조체 구조이다. 사용자가 수신받은 데이터를 기초로 해서 info 구조체의 항목에 각종 정보를 함수에서 설정한다. |
반환값
Tmax 서비스로 보낼 타입을 정의한다. TCPGW는 값을 바탕으로 Tmax로 어떤 처리를 할 것인지를 판단한다. 예를 들어 REMOTE_REQUEST는 리모트 노드로부터 Request가 발생한 것으로 판단하며, REMOTE_REPLY는 Tmax 서비스로부터 Request가 발생하여 리모트 노드로부터 Response가 오는 경우 반환하는 값이다. REMOTE_REPLY_CONT는 Response 메시지가 이어서 올 경우 반환하는 값이며, REMOTE_SENDTOCLI는 비요청 메시지일 경우 반환하는 값이다.
-1을 리턴 하고 환경설정파일의 CLOPT 절에 -e 옵션을 설정하면 해당 채널이 종료된다.
리모트 노드로부터 응답을 수신한 경우에는 반드시 UID 값을 info 구조체의 uid 항목에 지정해 주어야 한다. 기타 다른 값들은 상황에 맞게 주어야 한다.
Tmax 서비스나 클라이언트로부터 요청한 데이터를 리모트 노드에 전송할 때 사용자가 채널을 선택할 수 있도록 하는 함수이다. 사용자는 주어진 데이터의 특성에 따라서 전송할 채널을 지정할 수 있다. 단, 여기서 지정하는 것은 리모트 노드와 연결된 소켓 번호가 아니라 단순한 채널 번호이다. TCPGW는 사용자가 지정한 채널을 사용할 수 없으면 오류를 반환한다.
사용법
int get_channel_num(char *data)
파라미터
파라미터 | 설명 |
---|---|
data | 리모트 노드로 보내기 위한 데이터이다. |
반환값
채널 번호를 반환한다.
리모트 노드로 메시지를 전송하고자 할 때 호출되는 함수이다. 동기형 통신인 경우에는 사용자가 함수에서 UID를 메시지에 저장(Save)해야 한다. UID는 info 구조체의 uid 항목의 값을 사용해도 되고 또는 사용자가 임의의 UID를 생성해서 사용한 후에 info의 uid 항목에 넣어주면 된다.
사용자는 msg_header_t 구조체의 각각의 항목에 적절한 값을 저장해야 한다. 구조체는 사용자가 임의로 설정할 수 있는 항목이기 때문에 TCPGW에서는 msg_header_t의 구조체 항목에 어떤 값도 저장하지 않는다.
사용법
int put_msg_info(msg_header_t *hp, char *data, msg_info_t *info)
파라미터
파라미터 | 설명 |
---|---|
hp | 리모트 노드로 보낼 메시지의 헤더이다. |
data | 리모트 노드로 보낼 데이터이다. |
info | 리모트 노드로 보낼 데이터의 정보이다. |
반환값
사용자는 실제적으로 리모트 노드에 전송할 데이터의 전체 길이를 반환해야 한다. 메시지 헤더와 실 데이터를 더한 길이를 반환한다.
리모트 노드로 메시지를 전송한 후에 호출되는 함수로, 데이터가 완전히 리모트 노드에 전송되었다는 것을 알려주기 위해서 호출되는 함수이다.
사용법
int put_msg_complete(msg_header_t *hp, char *data, msg_info_t *info)
파라미터
파라미터 | 설명 |
---|---|
hp | 리모트 노드로 보낸 메시지의 헤더이다. |
data | 리모트 노드로 보낸 데이터이다. |
info | 리모트 노드로 보낸 데이터의 정보이다. |
Tmax에서 리모트 노드로 요청을 보낼 때 요청을 보내는 서버와 결과를 받는 서버를 달리하는 NON 블록형이나 비동기형 TCPGW를 구성하는 경우, tpreply()나 tpacall()을 할 서비스의 이름을 오류 코드에 따라서 설정한다.
사용법
int get_service_name(char *header, int err, char *svc)
파라미터
파라미터 | 설명 |
---|---|
header | [-H] 또는 [-h] 옵션으로 설정한 TCPGW에서 저장하고 있는 사용자 헤더의 포인터이다. |
err | 오류 코드이다. |
svc | tpreply()나 tpacall()를 받는 서비스의 이름을 설정한다. |
TCPGW가 종료하기 직전에 call되는 함수로, 일반적으로 init_remote_info() 함수에서 생성한 공유 메모리를 해제한다.
사용법
int prepare_shutdown(int code)
파라미터
파라미터 | 설명 |
---|---|
code | shutdown code로, 현재는 사용되지 않는다. |
서비스 타임아웃이 발생한 경우 사용자가 호출할 수 있는 함수이다.
사용법
int set_service_time_out(int uid, char *header)
파라미터
파라미터 | 설명 |
---|---|
uid | 서비스 타임아웃이 발생한 거래의 user ID이다. |
header | 서비스 타임아웃이 발생한 거래의 헤더이다. |
리모트 노드로부터 데이터를 수신할 때 데이터의 끝을 나타내는 특정 문자 혹은 비트 스트림이 존재할 경우 사용자가 호출할 수 있는 함수이다.
사용법
int chk_end_msg(int len, char *data)
파라미터
파라미터 | 설명 |
---|---|
len | 리모트 노드로부터 읽은 데이터 길이이다. |
data | 리모트 노드로부터 읽은 데이터 부분이다. |
노드로부터 요청을 tpacall(..., TPBLOCK)로 처리했을 때 서버가 떠 있지 않으면 에러가 돌아오게 되는데, 이러한 때에 호출된다. 사용자는 함수 내에서 적당히 새로운 데이터를 생성하고, 데이터의 크기를 반환한다.
사용법
int inmsg_recovery(char *data, msg_info_t *info)
파라미터
파라미터 | 설명 |
---|---|
data | 리모트 노드로부터 읽은 데이터 부분이다. |
info | 리모트 노드로부터 읽은 데이터의 정보로 의미있는 값은 다음과 같다.
|
반환값
사용자는 새로운 데이터의 길이를 반환해야 한다.
반환값 | 설명 |
---|---|
양수 |
|
음수 | 데이터를 버린다. |
리모트 노드로 요청을 보낼 때 에러가 발생할 경우 호출된다. 사용자는 함수 내에서 적당히 새로운 데이터를 생성하고 원하는 서비스명 및 UID 등을 설정하고, 데이터의 크기를 반환한다.
사용법
int inmsg_recovery(char *data, msg_info_t *info)
파라미터
파라미터 | 설명 |
---|---|
data | 리모트 노드로부터 읽은 데이터 부분이다. |
info | 리모트 노드로부터 읽은 데이터의 정보로 의미있는 값은 다음과 같다.
|
반환값
반환값 | 설명 |
---|---|
양수 |
|
get_msg_info와 기본적으로 기능은 동일하다. 단, 데이터 버퍼를 더블 포인터형으로 넘겨서 사용자가 버퍼의 메모리를 재할당(realloc)할 수 있다. 그러나 이 함수는 get_msg_info와 동시에 사용될 수 없으며, 사용하려면 TCPGW 컴파일할 때 -D_TCPGW_USE_EXTMSG flags를 설정해야 한다.
사용법
int get_extmsg_info(msg_header_t *hp, char **data, int asize, msg_info_t *info)
파라미터
파라미터 | 설명 |
---|---|
hp | 리모트 노드로부터 읽어온 메시지 헤더 데이터 대한 포인터이다. get_msg_length()에서 사용한 구조체와 동일하다. |
data | 리모트 노드로부터 읽은 데이터 버퍼의 주소값이다. |
asize | 리모트 노드로부터 읽은 데이터 버퍼에 할당된 메모리 크기이다. |
info | TCPGW 라이브러리(libtcpgw.a, libtcpgw.so)와 custom.c와 인터페이스 역할을 해주는 구조체 구조이다. 사용자가 수신받은 데이터를 기초로 해서 info 구조체의 항목에 각종 정보를 설정한다. |
반환값
Tmax 서비스로 보낼 타입을 정의한다. TCPGW는 값을 바탕으로 Tmax로 어떤 처리를 할 것인지를 판단한다. 예를 들어, REMOTE_REQUEST는 리모트 노드로부터 Request가 발생한 것으로 판단하며, REMOTE_REPLY는 Tmax 서비스로부터 Request가 발생하여 리모트 노드로부터 Response가 오는 경우 반환하는 값이다. REMOTE_REPLY_CONT는 Response 메시지가 이어서 올 경우 반환하는 값이며, REMOTE_SENDTOCLI는 비요청 메시지일 경우 반환하는 값이다. 리모트 노드로부터 응답을 수신한 경우에는 반드시 UID 값을 info 구조체의 uid 항목에 지정해 주어야 한다. 그리고 기타 다른 값들 상황에 맞게 주어야 한다.
put_msg_info와 기본적으로 기능은 동일하다. 단, 데이터 버퍼를 더블 포인터형으로 넘겨서 사용자가 버퍼의 메모리를 재할당(realloc) 할 수 있다. put_msg_info와 동시에 사용될 수 없으며, 사용하려면 TCPGW 컴파일할 때 -D_TCPGW_USE_EXTMSG flags를 설정해야 한다.
사용법
int put_extmsg_info(msg_header_t *hp, char **data, int asize, msg_info_t *info)
파라미터
파라미터 | 설명 |
---|---|
hp | 리모트 노드로 보낼 메시지의 헤더이다. |
data | 리모트 노드로 보낼 데이터 버퍼의 주소값이다. |
asize | 리모트 노드로 보낼 데이터 버퍼에 할당된 메모리 크기이다. |
info | 리모트 노드로 보낼 데이터의 정보이다. |
반환값
사용자는 함수에서 실제적으로 리모트 노드에 전송할 데이터의 전체 길이를 반환해야 한다. 메시지 헤더와 실 데이터를 더한 길이를 반환한다.
채널 장애 감시를 위해서 보낼 메시지나 메시지의 주기, 타임아웃 등을 설정할 수 있는 사용자 함수로 [–x] 옵션을 지정할 경우 반드시 설정해야 한다.
이 함수는 TCPGW 프로그램이 기동할 때 한 번 호출된다.
사용법
int set_ping_msg(msg_header_t *hp, int *interval, int *binterval, int *timeout, int *mode)
파라미터
파라미터 | 설명 |
---|---|
hp | 채널 장애 감시를 위해서 주기적으로 보내지는 메시지이다. 사용자는 이 메시지를 설정해야 한다. |
interval | 채널 장애 감시 주기이다. 0일 경우 채널 장애 감지 기능은 비활성화된다. (단위: 초) |
binterval | 백업 채널 모드일 때 메인 채널의 상태를 체크하는 주기이다. 0 일 경우 메인 채널의 상태 체크 기능은 비활성화된다. (단위: 초) |
timeout | 채널 장애 감시 타임아웃으로 시간 내에 응답이 오지 않으면 채널의 연결은 끊어진다. (단위: 초) 실제로 채널의 연결이 종료되는 시점은 interval 주기에 따라 ping 메시지를 전송할 때 reset_ping_msg()가 호출되기 전이다. 0일 경우에는 Ping 메시지만 보내고 Pong 메시지에 대해서는 신경쓰지 않는다. (Half Duplex 장애 감지) |
mode | 장애 감시할 채널 종류를 지정한다.
|
반환값
에러가 발생할 때 음수값을 반환해야 하며, 이 경우 장애 감시 기능은 비활성화된다.
리모트 서버로부터 메시지를 수신했을 때 해당 메시지가 채널 장애 감지를 위한 응답 메시지인지를 여부를 확인하는 함수이다.
사용법
int chk_pong_msg(msg_header_t *hp)
파라미터
파라미터 | 설명 |
---|---|
hp | 리모트로부터 수신된 메시지이다. |
반환값
반환값 | 설명 |
---|---|
양수 | 리모트 서버로부터 수신한 메시지가 정상적인 채널 장애 감시 응답 메시지인 경우이다. |
0 | 리모트 서버로부터 수신한 메시지는 채널 장애 감시 응답 메시지가 아닌 일반적인 메시지인 경우이다. 해당 메시지는 get_msg_info 함수에서 처리된다. |
음수 | 리모트 서버로부터 수신한 메시지가 비정상적인 채널 장애 감시 응답 메시지인 경우이다. 해당 채널을 종료시킨다. |
채널 장애 감시를 위해 보낼 메시지나 메시지의 주기, 타임아웃 등을 설정할 수 있는 사용자 함수로 [–x] 옵션을 지정할 경우 반드시 설정해야 한다.
이 함수는 TCPGW 프로그램이 기동할 때 한 번 호출된다.
사용법
int set_extping_msg(msg_header_t *hp, char *data, int len, int *interval, int *binterval, int *timeout, int *mode)
파라미터
파라미터 | 설명 |
---|---|
hp | 채널 장애 감시를 위해서 주기적으로 보내지는 메시지이다. 사용자는 이 메시지를 설정해야 한다. |
data | 채널 장애 감시를 위해서 주기적으로 보내지는 메시지 뒤에 함께 전송될 메시지 바디이다. 필요한 경우에 설정한다. |
len | 채널 장애 감지 메시지 바디의 최대 길이이다. [-b] 옵션으로 최대 길이를 설정하고, 지정하지 않으면 크기는 0이다. |
interval | 채널 장애 감시 주기이다. 0일 경우 채널 장애 감지 기능은 비활성화된다. (단위: 초) |
binterval | 백업 채널 모드일 때 메인 채널의 상태를 체크하는 주기이다. 0일 경우 메인 채널의 상태 체크 기능은 비활성화된다. (단위: 초) |
timeout | 채널 장애 감시 타임아웃으로 시간 내에 응답이 오지 않으면 채널의 연결은 끊어진다. (단위: 초) 0일 경우에는 Ping 메시지만 보내고 Pong 메시지에 대해서는 신경쓰지 않는다. (Half Duplex 장애 감지) |
mod |
|
반환값
반환값 | 설명 |
---|---|
0 | 함수 수행이 성공한 경우이다. |
음수 | 함수 수행이 실패한 경우이다. |
예제
int set_extping_msg(msg_header_t *hp, char *data, int len, int *interval, int *binterval, int *timeout, int *mode) { msg_body_t *body; body = (msg_body_t *)data; memset(body->data, 0x00, 52); memcpy(body->data, "tmax50", 7); body->data[51] = 0; printf("set_extping_msg : data = %s\n", body->data); hp->len = 7; *interval = 10; *binterval = 20; *timeout = 100; *mode = 0; /* OUTBOUND CHANNEL */ return 1; }
리모트 서버로부터 메시지를 수신했을 때 해당 메시지가 채널 장애 감지를 위한 응답 메시지인지를 확인하는 함수이다.
사용법
int chk_extpong_msg(msg_header_t *hp, char *data, int len)
파라미터
파라미터 | 설명 |
---|---|
hp | 채널 장애가 감지되었을 때 리모트 서버로부터 수신된 메시지 헤더이다. |
data | 채널 장애가 감지되었을 때 리모트 서버로부터 수신된 메시지 바디이다. |
len | 수신된 메시지 바디의 길이이다. |
반환값
반환값 | 설명 |
---|---|
양수 | 리모트 서버로부터 수신한 메시지가 정상적인 채널 장애 감시 응답 메시지인 경우이다. |
0 | 리모트 서버로부터 수신한 메시지는 채널 장애 감시 응답 메시지가 아닌 일반적인 메시지이다. 해당 메시지는 get_msg_info 함수에서 처리된다. |
음수 | 리모트 서버로부터 수신한 메시지가 비정상적인 채널 장애 감시 응답 메시지인 경우이다. 해당 채널을 종료시킨다. |
예제
int chk_extpong_msg(msg_header_t *hp, char *data, int len) { msg_body_t *body; char data2[15]; body = (msg_body_t *)data; printf("chk_extpong_msg : data = %s\n", body->data); if (strcmp(body->data, "ping_reply") return 1; return 0; }
채널 장애 감지(TCP/IP ping) 메시지의 전송 여부를 결정하고, 전송 메시지를 재설정하기 위해 주기적으로 호출되는 함수이다.
set_ping_msg 함수에서 설정한 interval 주기에 따라 ping 메시지를 리모트 서버로 전송하기 전에, 이 함수가 호출되어 전송 메시지를 확인하고 필요한 경우 수정할 수 있다. 또한 반환값에 따라 ping 메시지를 리모트 서버에 전송할지 여부를 결정한다.
사용법
int reset_ping_msg(msg_header_t *hp)
파라미터
파라미터 | 설명 |
---|---|
hp | 채널 장애 감지를 위해 전송할 메시지의 헤더이다. 기본값으로 set_ping_msg 함수에서 사용자가 정의한 헤더가 설정된다. |
반환값
반환값 | 설명 |
---|---|
양수 | ping 메시지를 리모트 서버로 전송한다. |
음수 | ping 메시지를 리모트 서버로 전송하지 않는다. |
예제
int reset_ping_msg(msg_header_t *hp) { hp->len = 0; hp->msgtype = HEALTH_CHECK; return 1; }
채널 장애 감지(TCP/IP ping) 메시지의 전송 여부를 결정하고, 전송 메시지를 재설정하기 위해 주기적으로 호출되는 함수이다.
set_ping_msg 함수에서 설정한 interval 주기에 따라 ping 메시지를 리모트 서버로 전송하기 전에, 이 함수가 호출되어 전송 메시지를 확인하고 필요한 경우 수정할 수 있다. 또한 반환값에 따라 ping 메시지를 리모트 서버에 전송할지 여부를 결정한다.
사용법
int reset_extping_msg(msg_header_t *hp, char *data, int len)
파라미터
파라미터 | 설명 |
---|---|
hp | 채널 장애 감지를 위해 전송할 메시지의 헤더이다. 기본값으로 set_ping_msg 함수에서 사용자가 정의한 헤더가 설정된다. |
data | 재설정할 메시지 바디의 포인터이다. 버퍼의 최대 크기는 len 에 설정된 크기이다. 실제 전송할 버퍼의 크기는 반환값에 지정한다. |
len | 사용 가능한 메시지 바디의 최대 크기이다. |
반환값
반환값 | 설명 |
---|---|
양수 | ping 메시지를 리모트 서버로 전송한다. 지정된 크기만큼의 메시지 바디를 전송한다. |
0 | ping 메시지를 리모트 서버로 전송한다. 메시지 바디를 전송하지 않는다. |
음수 | ping 메시지를 리모트 서버로 전송하지 않는다. |
예제
int reset_extping_msg(msg_header_t *hp, char *data, int len) { int body_len; char *message = "reset_msg"; body_len = min(len, strlen(message)); strncpy(data, message, (body_len - 1)); data[(body_len - 1)] = '\0'; hp->len = body_len; printf("reset_extping_msg : data = %s\n", data); return body_len; }
TCPGW를 통한 리모트 노드와의 거래 도중 타임아웃 혹은 네트워크 단절과 같은 에러가 발생했을 경우 자동으로 호출되는 함수로, 해당 함수 내에서 사용자는 사용자 헤더 또는 사용자 데이터를 수정할 수 있다.
사용법
int set_error_msg(msg_header_t *hp, int err, char *data, int len)
파라미터
파라미터 | 설명 |
---|---|
hp | 에러가 발생했을 경우 전송된 메세지의 헤더로 사용자가 수정할 수 있다. |
data | 에러가 발생했을 경우 전송된 데이터로 사용자가 수정할 수 있다. |
len | 메시지 바디의 길이이다 |
반환값
반환값 | 설명 |
---|---|
양수 | 리턴한 길이만큼의 데이터를 전송한다. 단, 이 경우 CLOPT="-I" 옵션을 설정해야만 적용된다. |
0 | 사용자 헤더 부분까지만 전송한다. |
음수 | 해당 메세지를 CLH로 전송하지 않는다. |
오류
에러 코드 | 설명 |
---|---|
[TPECLOSE] | 리모트 노드로 서비스를 요청한 이후에 리모트 노드와 연결이 끊어진 경우에 발생한다. |
[TPENOENT] | [-E] 옵션을 사용할 경우 서비스 요청마다 리모트 노드와 연결을 하고 데이터를 전송하는데, 동시에 호출한 수가 [-n] 옵션으로 지정한 채널의 수를 초과했을 때 발생한다. |
[TPENOREADY] | 리모트 노드와의 연결이 끊어져 사용할 수 있는 채널이 없는 경우에 발생한다. |
[TPEOS] | TCPGW 내부에서 메모리를 확보하는데, 확보되지 않을 경우에 발생한다. |
[TPEPROTO] | tpforward로 TCPGW를 호출할 때 TCPGW가 동기형 모드가 아닌 비동기형 모드일 경우 발생한다. tpforward & tprelay 방식은 반드시 동기형 방식이어야 한다. |
[TPESVCERR] | put_msg_info 에서 0 혹은 음수를 리턴하는 경우 발생한다. |
[TPESYSTEM] | TCPGW에서 코드 변환을 사용할 때 요청한 데이터에 대한 map 파일이 로드되지 않을 경우에 발생한다. 또는 코드 변환오류가 발생하여 사용자 함수 put_msg_info에서 음수를 반환한 경우 리모트 노드로 데이터를 전송할 때 오류가 발생한 경우이다. |
[TPETIME] | 리모트 노드로 서비스를 요청하고 지정된 시간 내에 응답이 없을 경우에 발생한다. |
예제
int set_error_msg(msg_header_t *hp, int err, char *data, int len) { msg_body_t * body; body = (msg_body_t *)data; strcpy(body->data, "changed hello data"); /* 에러 메시지에는 데이터가 포함되지 않으므로 데이터 부분까지 전달되기 위해서는 -I 옵션을 사용해야 한다. 사용하지 않을 시 사용자 헤더까지만 CLH로 전달된다. */ /* 사용자헤더가 없는 경우에 hp와 data의 값이 같을 수 있다. */ strcpy(hp->retsvcname, "RECVSVC_CHANGE"); return len; }
get_msg_info() 또는 get_extmsg_info() 함수가 수행된 후에 호출되는 함수이다. 사용자 데이터를 가공할 필요가 있을 경우에 사용한다. get_extmsg_info() 함수가 이 함수를 대체할 수 있다.
사용법
int get_msg_security(char **data, int asize, int len)
파라미터
파라미터 | 설명 |
---|---|
data | 리모트 노드로부터 읽은 데이터 버퍼의 주소값이다. 버퍼의 크기가 부족한 경우에는 realloc()을 통해 버퍼를 확장하는 것을 허용한다. realloc()을 호출하여 버퍼의 포인터가 변경된 경우에는 이 주소값에 변경된 포인터 주소값을 저장해야 한다. |
asize | 리모트 노드로부터 읽은 데이터 버퍼에 할당된 메모리 크기이다. |
len | 메시지 바디의 길이이다 |
반환값
반환값 | 설명 |
---|---|
양수 | 가공된 사용자 데이터의 전체 길이를 리턴한다. |
0 | 사용자 데이터의 변경사항을 반영하지 않는다. |
예제
int get_msg_security(char **data, int asize, int len) { ... new_size = len * 2; if (new_size > asize) { tmpbuf = (char *)realloc(*data, new_size); if (tmpbuf == NULL) { /* error processing */ } *data = tmpbuf; } ... return new_size; }
put_msg_info() 또는 put_extmsg_info() 함수가 수행되기 전에 호출되는 함수이다. 사용자 데이터를 가공할 필요가 있을 경우에 사용한다. put_extmsg_info() 함수가 이 함수를 대체할 수 있다.
사용법
int put_msg_security(char **data, int asize, int len)
파라미터
파라미터 | 설명 |
---|---|
data | 리모트 노드로 보낼 데이터 버퍼의 주소값이다. 버퍼의 크기가 부족한 경우에는 realloc() 을 통해 버퍼를 확장하는 것을 허용한다. realloc()을 호출하여 버퍼의 포인터가 변경된 경우에는 이 주소값에 변경된 포인터 주소값을 저장해야 한다. |
asize | 리모트 노드로 보낼 데이터 버퍼에 할당된 메모리 크기이다. |
len | 메시지 바디의 길이이다 |
반환값
반환값 | 설명 |
---|---|
양수 | 가공된 사용자 데이터의 전체 길이를 리턴한다. |
0 | 사용자 데이터의 변경사항을 반영하지 않는다. |
예제
int put_msg_security(char **data, int asize, int len) { ... new_size = len * 2; if (new_size > asize) { tmpbuf = (char *)realloc(*data, new_size); if (tmpbuf == NULL) { /* error processing */ } *data = tmpbuf; } ... return new_size; }
사용자 함수 등록 파일로, 사용자가 등록한 함수들만 게이트웨이 라이브러리에서 호출된다. 게이트웨이를 컴파일할 때 반드시 register.c를 포함시켜야 한다. 사용하지 않는 함수는 NULL 등록하면 된다.
다음은 register.c 예제이다.
/* --------------------- tcpgw register.c ------------------------ */ #include <stdio.h> #include <arpa/inet.h> #include "custom.h" extern int _tcpgw_regfn_init(); extern int _tcpgw_regfn(int type, void *regFn); extern int init_remote_info(char *myname, int mynumber, int num_channel, int key); extern int prepare_shutdown(int code); extern int remote_connected(int index, int addr, int portno, int type, int fd); extern int remote_connected_ipv6(int index, struct sockaddr *saddr, int portno, int type, int fd); extern int remote_closed(int index, int type); extern int get_msg_length(msg_header_t * hp); extern int get_msg_info(msg_header_t * hp, char *data, msg_info_t * info); extern int put_msg_info(msg_header_t * hp, char *data, msg_info_t * info); extern int put_msg_complete(msg_header_t * hp, char *data, msg_info_t * info); extern int get_channel_num(char *data); extern int get_service_name(char *header, int err, char *svc); extern int set_service_timeout(int uid, char *header); extern int get_msg_security(char **data, int asize, int len); extern int put_msg_security(char **data, int asize, int len); extern int chk_end_msg(int len, char *data); extern int get_extmsg_info(msg_header_t * hp, char **data, int asize, msg_info_t * info); extern int put_extmsg_info(msg_header_t * hp, char **data, int asize, msg_info_t * info); extern int inmsg_recovery(char *data, msg_info_t * info); extern int outmsg_recovery(char *data, msg_info_t * info); extern int set_ping_msg(msg_header_t * hp, int *interval, int *bintrval, int *timeout, int *mode); extern int chk_pong_msg(msg_header_t * hp); extern int set_extping_msg(msg_header_t * hp, char *data, int len, int *interval, int *bintrval, int *timeout, int *mode); extern int chk_extpong_msg(msg_header_t * hp, char *data, int len); extern int reset_ping_msg(msg_header_t * hp); extern int reset_extping_msg(msg_header_t * hp, char *data, int len); extern int set_error_msg(msg_header_t * hp, int err, char *data, int len); extern int allow_connection(int addr, int portno, int type, int fd); extern int allow_connection_ipv6(struct sockaddr *saddr, int portno, int type, int fd); /************************************************************************** * int * _register_custom() * * returns no used * [function number] * 1. init_remote_info * 2. prepare_shutdown * 3. remote_connected * 4. remote_closed * 5. get_msg_length * 6. get_msg_info * 7. put_msg_info * 8. put_msg_complete * 9. get_channel_num * 10. get_service_name * 11. set_service_timeout * 12. get_msg_security * 13. put_msg_security * 14. chk_end_msg * 15. get_extmsg_info * 16. put_extmsg_info * 17. inmsg_recovery * 18. outmsg_recovery * 19. set_ping_msg * 20. chk_pong_msg * 21. set_extping_msg * 22. chk_extpong_msg * 23. reset_ping_msg * 24. reset_extping_msg * 25. set_error_msg * 26. allow_connection * 27. allow_connection_ipv6 * 28. remote_connected_ipv6 **************************************************************************/ int _register_custom() { _tcpgw_regfn_init(); _tcpgw_regfn(1, init_remote_info); _tcpgw_regfn(2, prepare_shutdown); _tcpgw_regfn(3, remote_connected); _tcpgw_regfn(4, remote_closed); _tcpgw_regfn(5, get_msg_length); #if defined(_TCPGW_USE_EXTMSG) _tcpgw_regfn(15, get_extmsg_info); _tcpgw_regfn(16, put_extmsg_info); #else _tcpgw_regfn(6, get_msg_info); _tcpgw_regfn(7, put_msg_info); #endif _tcpgw_regfn(8, put_msg_complete); _tcpgw_regfn(9, get_channel_num); _tcpgw_regfn(10, get_service_name); _tcpgw_regfn(11, set_service_timeout); #if defined(_TCPGW_USE_EXTPING) _tcpgw_regfn(21, set_extping_msg); _tcpgw_regfn(22, chk_extpong_msg); #else _tcpgw_regfn(19, set_ping_msg); _tcpgw_regfn(20, chk_pong_msg); #endif #if defined(_TCPGW_VERSION_OLD) #elif defined(_TCPGW_VERSION_1) _tcpgw_regfn(12, get_msg_security); _tcpgw_regfn(14, chk_end_msg); #elif defined(_TCPGW_VERSION_2) _tcpgw_regfn(12, get_msg_security); _tcpgw_regfn(14, chk_end_msg); _tcpgw_regfn(17, inmsg_recovery); _tcpgw_regfn(18, outmsg_recovery); #else _tcpgw_regfn(14, chk_end_msg); _tcpgw_regfn(17, inmsg_recovery); _tcpgw_regfn(18, outmsg_recovery); #endif return 1; }