Discussion:
when i detach a session,but the other side can not stop the session,and can not kill the session,how can i change the code
(too old to reply)
zhangych
2009-05-12 13:53:53 UTC
Permalink
I rewrite a appc program from the CPIC,to change tcpip to sna server from
aix system.when i
close the sna with verb AP_M_DEALLOCATE,AP_AP_ABEND or AP_FLUSH and
AP_TP_ENDED to terminate the session,normally,the both side of session is
closed correct.
But sometime,the session at aix is ok,but at os/390 side,the session is
hungup,and can not stop with command,but the transaction is commit with the
verb AP_M_CONFIRMED.only when i stop the process ,the sesssion hunguped will
free.I found nothing in the /var/sna logfile.

the program is,in function FcaReadRequest,F001 attach sna and sendrec from
390,F003 just send to host, F004 send and recv then detach:
#include "hiserver.h"
#include "hitermsna.h"
#include <sys/socket.h>
#include <sys/select.h>
#include <netinet/in.h>

typedef struct{
int sockfd;
char rmt_ip[15];
long rmt_port;
long timestamp;
} CONN_DESP;

#define MAX_LEN (8192+4)
#define HOST_HEAD_LEN (54)

short _IntervalCheckTime; /* function peerCloseMonitor check loop interval
*/
short _HeadLen; /* the recv buff headlength,if set to 0 the recv
buff only body no head */
short _MAXWORKER; /* define the max workers to paralling read fromt
socket */

char msg_type[MSG_TYPE_LEN+1];
int listenfd;
int thread_num;
pthread_t * main_thread_id;
pthread_mutex_t acptlock = PTHREAD_MUTEX_INITIALIZER;

int initSnaParm(int argc, char ** argv)
{
int errno,i;

if (argc < 5){
apperr("initSnaParm input para: ltpname llualias ptpname plualias
modename\n");
return(-1);
}

/* init the gobal structure acfg,with the sna parameter */
/* ltpname:local tp name, llualias:local lu alias */
/* ptpname:partner tp name,plualias:partner lu alias */
/* modename:transfer mode name */
memset(&acfg, 0x20, sizeof(acfg));
memcpy(acfg.ltpname, argv[0], strlen(argv[0])); /* CPIC_DEFAULT_TPNAME
*/
memcpy(acfg.llualias, argv[1], strlen(argv[1]));
memcpy(acfg.ptpname, argv[2], strlen(argv[2]));
memcpy(acfg.plualias, argv[3], strlen(argv[3]));
memcpy(acfg.modename, argv[4], strlen(argv[4]));

return(0);
}

/* read sock data from client */
int readClientData(int sockfd, unsigned char ** rcvptr, int * rcvlen, int
timeout)
{
int rc = 0;
int hdlen = 0, msglen = 0;
int i = 0;
unsigned char hdbuf[HOST_HEAD_LEN+1];
unsigned char mlenbuf[7];

/* check timeout happened */
rc = TcpSelectSocket(timeout, sockfd);
if(rc < 0) {
apperr("readClientData TcpSelectSocket fail[%d]\n", rc);
return(-1);
}else if(rc == 0) {
apperr("readClientData TcpSelectSocket TimeOut happend.\n");
return(-2);
}

/* if have head buffer, receive head first, then malloc specified
string to receive */
memset(hdbuf, 0x00, sizeof(hdbuf));
hdlen = ReadN(sockfd, hdbuf, HOST_HEAD_LEN);
if(hdlen != HOST_HEAD_LEN) {
apperr("readClientData func ReadN read headlen buffer error.\n");
return(-3);
}
memset(mlenbuf, 0x00, sizeof(mlenbuf));
memcpy(mlenbuf, &hdbuf[48], 6);
for(i=0; i<6; i++)
mlenbuf[i] = mlenbuf[i] - 0xC0;

msglen = atoi((char *)mlenbuf);
if(msglen<=0 || msglen>=10240) {
apperr("readClientData recv length[%d] error.\n", msglen);
return(-4);
}

*rcvptr = malloc(msglen+HOST_HEAD_LEN+1);
if(*rcvptr == NULL) {
apperr("readClientData malloc rcvptr error.\n");
return(-5);
}
memset(*rcvptr, 0x00, msglen+1);
memcpy(*rcvptr, hdbuf, HOST_HEAD_LEN);

rc = TcpSelectSocket(timeout, sockfd);
if(rc < 0) {
apperr("readClientData TcpSelectSocket Body fail[%d]\n", rc);
free(*rcvptr);
*rcvptr = NULL;
return(-6);
}else if(rc == 0) {
apperr("readClientData TcpSelectSocket TimeOut happend.\n");
free(*rcvptr);
*rcvptr = NULL;
return(-7);
}

*rcvlen = ReadN(sockfd, *rcvptr+HOST_HEAD_LEN, msglen);
if(*rcvlen != msglen) {
apperr("readClientData recv length[%d],should be[%d] error.",
rcvlen, msglen);
free(*rcvptr);
*rcvptr = NULL;
return(-8);
}

*rcvlen = msglen + HOST_HEAD_LEN;

return(0);
}

/* write host data to client */
int writeHostData(int sockfd, unsigned char * sndbuf, int sndlen)
{
int len = 0;

len = WriteN( sockfd, sndbuf, sndlen);
if ( len != sndlen ) {
apperr("writeHostData tcp WriteN send data error.\n");
TcpCloseSocket(sockfd);
return(-1);
}

return(0);
}

/* Receive client request;Send to Host;Recv from Host Write to client. */
void * FcaReadRequest(void *arg)
{
CONN_DESP * conn_desp = (CONN_DESP *)arg;
APPC_RES appcres;
char recbuf[10];
char ptpname[64];
unsigned char rcv_buf[MAX_LEN+1];
unsigned char * snd_ptr = NULL;
int msg_len = 0, rc = 0, recnum = 0, i = 0;
int conn_fd, rcv_len, snd_len;
long timestamp = 0L;
struct timeval ct;
struct timezone zone;

pthread_detach(pthread_self());

/* record the in tran's socket information for manage later in
FcaWriteResponse
and peerCloseMonitor thread */
conn_fd = conn_desp->sockfd;
free( conn_desp );
gettimeofday(&ct, &zone);
timestamp = ct.tv_sec;

for(;;) {
/* read from the client,if no length define using recv else use readN
*/
rc = readClientData(conn_fd, &snd_ptr, &snd_len,
_IntervalCheckTime);
if(rc != 0) {
apperr("FcaReadRequest readClientData execute fail.\n");
TcpCloseSocket(conn_fd);
pthread_exit(NULL);
}
if(rcv_len == 0) {
apperr("FcaReadRequest readClientData rcv_len is zero.\n");
TcpCloseSocket(conn_fd);
pthread_exit(NULL);
}

/* check the message type to process it */
/* the first package,attach the sna,send and recv with Host */
if(memcmp(snd_ptr+8, "F001", 4) == 0) {
apphex("Send T Host EBCDIC INIT Buff:", snd_ptr, snd_len);

memset(rcv_buf, 0x00, sizeof(rcv_buf));
rcv_len = sizeof(rcv_buf);

memset(&appcres, 0x00, sizeof(appcres));
appcres.convid = -1;

memset(ptpname, ' ', sizeof(ptpname));
memcpy(ptpname, acfg.ptpname, sizeof(acfg.ptpname));

rc = attachSna(&appcres, ptpname);
if (rc < 0) {
detachSna(&appcres);
apperr("FcaReadRequest attachSna Execute Fail!\n");
TcpCloseSocket(conn_fd);
free(snd_ptr);
snd_ptr = NULL;
pthread_exit(NULL);
}

rc = sndrcvSna(&appcres, snd_ptr, snd_len, rcv_buf, (unsigned
int *)&rcv_len);
if (rc < 0 || rcv_len < 0) {
detachSna(&appcres);
apperr("FcaReadRequest sndrcvSna data Fail!\n");
TcpCloseSocket(conn_fd);
free(snd_ptr);
snd_ptr = NULL;
pthread_exit(NULL);
}
free(snd_ptr);
snd_ptr = NULL;

apphex("Recv F Host EBCDIC INIT Buff:", rcv_buf, rcv_len);

rc = writeHostData(conn_fd, rcv_buf, rcv_len);
if(rc != 0) {
apperr("FcaReadRequest writeHostData execute fail.\n");
detachSna(&appcres);
TcpCloseSocket(conn_fd);
pthread_exit(NULL);
}

}
else if(memcmp(snd_ptr+8, "F003", 4) == 0) {
apphex("Send T Host EBCDIC SEND Buff:", snd_ptr, snd_len);

rc = sndSyncSna(&appcres, snd_ptr, snd_len);
if (rc < 0) {
detachSna(&appcres);
apperr("FcaReadRequest sndSyncSna data Fail!\n");
TcpCloseSocket(conn_fd);
free(snd_ptr);
snd_ptr = NULL;
pthread_exit(NULL);
}
free(snd_ptr);
snd_ptr = NULL;

}
else if(memcmp(snd_ptr+8, "F004", 4) == 0) {
apphex("Send T Host EBCDIC ENDF Buff:", snd_ptr, snd_len);

memset(rcv_buf, 0x00, sizeof(rcv_buf));
rcv_len = sizeof(rcv_buf);

rc = sndrcvSna(&appcres, snd_ptr, snd_len, rcv_buf, (unsigned
int *)&rcv_len);
if (rc < 0 || rcv_len < 0) {
detachSna(&appcres);
apperr("FcaReadRequest endf sndrcvSna data Fail!\n");
TcpCloseSocket(conn_fd);
free(snd_ptr);
snd_ptr = NULL;
pthread_exit(NULL);
}
free(snd_ptr);
snd_ptr = NULL;

rc = cfmSna(&appcres);
if (rc < 0) {
detachSna(&appcres);
apperr("FcaReadRequest cfmSna data Fail!\n");
TcpCloseSocket(conn_fd);
pthread_exit(NULL);
}
appcres.convid = 0;
detachSna(&appcres);

apphex("Recv F Host EBCDIC ENDF Buff:", rcv_buf, rcv_len);

rc = writeHostData(conn_fd, rcv_buf, rcv_len);
if(rc != 0) {
apperr("FcaReadRequest writeHostData execute fail.\n");
TcpCloseSocket(conn_fd);
pthread_exit(NULL);
}
TcpCloseSocket(conn_fd);
pthread_exit(NULL);
}
else {
apphex("Send T Host EBCDIC TYPE Buff:", snd_ptr, snd_len);
apperr("FcaReadRequest rcvptr error data type!\n");
TcpCloseSocket(conn_fd);
free(snd_ptr);
snd_ptr = NULL;
pthread_exit(NULL);
}

}
pthread_exit(NULL);
}

/* the main thread which accept the clients' request with the mutex lock.
*/
void * FcaAccept(void *arg)
{
socklen_t cli_len;
int errno;
struct sockaddr_in cli_addr;
pthread_t thread_id = 0;
pthread_attr_t attr;
void *FcaReadRequest(void *);
CONN_DESP * conn_desp = NULL;

pthread_detach(pthread_self());

if (pthread_attr_init(&attr) != 0) {
apperr("FcaAccept init thread attr error.\n");
pthread_exit(NULL);
}
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM);

memset((char *)&cli_addr, 0, sizeof(struct sockaddr_in));
for (;;) {
cli_len = sizeof(cli_addr);
conn_desp = (CONN_DESP *)malloc(sizeof(CONN_DESP));
if ( conn_desp == NULL ) {
apperr("FcaAccept malloc CONN_DESP error.\n");
continue;
}
memset( conn_desp, 0, sizeof(CONN_DESP) );

pthread_mutex_lock(&acptlock);
conn_desp->sockfd = accept(listenfd, (struct sockaddr *)&cli_addr,
&cli_len);
pthread_mutex_unlock(&acptlock);

if (conn_desp->sockfd < 0) {
apperr("FcaAccept tcp accept connect error");
free(conn_desp);
continue;
}
sprintf(conn_desp->rmt_ip, "%s", inet_ntoa(cli_addr.sin_addr));
conn_desp->rmt_port = ntohs(cli_addr.sin_port);

errno = pthread_create( &thread_id, &attr, FcaReadRequest, (void
*)conn_desp);
if ( errno )
ERRLOG(100501, "FcaAccept create thread FcaReadRequest error" );
}
}

/* The entrance function of the fca server which receive client's request
*/
int FcaLongIn(int argc, char ** argv,pthread_t * tid)
{
void *FcaAccept(void *);
pthread_t thread_id;
pthread_attr_t attr;
int errno,i;

if (argc < 2){
apperr("FcaLongIn input para: MsgType PortNo MaxWorker
IntervalCheckTime");
return(-1);
}

/* get the msg type to send */
memset(msg_type, 0x00, sizeof(msg_type));
strcpy(msg_type, argv[0] );

/* define the max worker to read from the socket */
if(argc >= 2)
_MAXWORKER = (atoi(argv[2])>20 ? atoi(argv[2]) : 20);
else
_MAXWORKER = 10;

/* loop monitor CONN_DESP structure interval time */
_IntervalCheckTime = (argc >= 3 ? atoi(argv[3]) : 5);

/* create the structure to store the thread to free at dlldone */
thread_num = 5;
main_thread_id = (pthread_t *)malloc((thread_num)*sizeof(pthread_t));
if(main_thread_id == NULL) {
apperr("FcaLongIn malloc main_thread_id error!\n");
return(-1);
}

listenfd = TcpBindSocketPortListen( atoi(argv[1]) );
if(listenfd < 0 ) {
apperr("FcaLongIn TcpBindSocketPortListen error!\n");
return(-1);
}

if (pthread_attr_init(&attr) != 0) {
apperr("FcaLongIn init thread attr fail!\n" );
return (-1);
}
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM);

for ( i = 0; i < 5; i++ ){
errno = pthread_create(&thread_id, &attr, FcaAccept, NULL);
if ( errno )
apperr("FcaLongIn thread FcaAccept create fail!\n" );
main_thread_id[i] = thread_id;
}

pthread_attr_destroy(&attr);

return(0);
}

void dlldone()
{
int i,errno;

for ( i = 0; i < thread_num; i++ ){
errno = pthread_cancel( main_thread_id[i] );
if ( errno )
apperr("dlldone cancel thread error.\n");
}

close(listenfd);
}


==================================================================
function use in lib:
int attachSna(APPC_RES * appcres, char * ptpname)
{
struct tp_started tpstart;
struct mc_allocate mcalloc;

if(appcres == NULL) {
apperr("attachSna parameter fail!\n");
return(-1);
}

memset(&tpstart, 0x00, sizeof(tpstart));
tpstart.opcode = AP_TP_STARTED;
cnvASC2EBC((unsigned char *)acfg.ltpname, sizeof(acfg.ltpname),
tpstart.tp_name); /* set the local tp name */
memcpy(tpstart.lu_alias, acfg.llualias, sizeof(acfg.llualias)); /*
set the local lu alias name */

APPC(&tpstart);
if(tpstart.primary_rc != AP_OK) {
apperr("attachSna tpstart ErrInfo
[%s][%s]\n",getPrmErrInfo(tpstart.primary_rc),getSecErrInfo(tpstart.secondary_rc));
return(-1);
}else {
memcpy(appcres->tpid, tpstart.tp_id, sizeof(appcres->tpid));
}

memset(&mcalloc, 0x00, sizeof(mcalloc));
mcalloc.opcode = AP_M_ALLOCATE;
mcalloc.opext = AP_MAPPED_CONVERSATION;
mcalloc.format = 1;
memcpy(mcalloc.tp_id, appcres->tpid, sizeof(appcres->tpid));
mcalloc.sync_level = AP_CONFIRM_SYNC_LEVEL;
mcalloc.rtn_ctl = AP_WHEN_SESSION_ALLOCATED;
mcalloc.security = AP_NONE;
cnvASC2EBC((unsigned char *)ptpname, sizeof(acfg.ptpname),
mcalloc.tp_name); /* set the partner tp name */
cnvASC2EBC((unsigned char *)acfg.modename, sizeof(acfg.modename),
mcalloc.mode_name); /* set the trans mode name */
memcpy(mcalloc.plu_alias, acfg.plualias, sizeof(acfg.plualias));
/* set the partner lu alias name */

APPC(&mcalloc);
if(mcalloc.primary_rc != AP_OK) {
apperr("attachSna mcalloc tp_id [%08X%08X],ErrInfo [%s][%s]\n",
dspTpId(mcalloc.tp_id),dspTpId(&mcalloc.tp_id[4]),getPrmErrInfo(mcalloc.primary_rc),getSecErrInfo(mcalloc.secondary_rc));
return(-1);
}else {
appcres->convid = mcalloc.conv_id;
return(0);
}
}

int sndrcvSna(APPC_RES * appcres, unsigned char *sndbuf, unsigned int
sndlen, unsigned char *rcvbuf, unsigned int *rcvlen)
{
struct mc_send_data mcsend;
struct mc_receive_and_wait mcrec;

if(appcres == NULL || sndbuf == NULL || sndlen <= 0 || rcvbuf == NULL ||
*rcvlen <= 0) {
apperr("sndrcvSna parameter fail!\n");
return(-1);
}

/* initial the mcsend struct,prepare the sending operation */
memset(&mcsend, 0x00, sizeof(mcsend));
mcsend.opcode = AP_M_SEND_DATA;
mcsend.opext = AP_MAPPED_CONVERSATION;
mcsend.format = 1;
memcpy(mcsend.tp_id, appcres->tpid, sizeof(appcres->tpid));
mcsend.conv_id = appcres->convid;
mcsend.dlen = sndlen;
mcsend.dptr = sndbuf;
mcsend.type = AP_SEND_DATA_P_TO_R_CONFIRM;

/* proccessing the sending operation */
APPC(&mcsend);
/* check SEND_DATA verb is process successful */
if(mcsend.primary_rc != AP_OK) {
apperr("sndrcvSna mcsend tp_id [%08X%08X] conv_id [%08X],ErrInfo
[%s][%s]\n",
dspTpId(mcsend.tp_id),dspTpId(&mcsend.tp_id[4]),mcsend.conv_id,getPrmErrInfo(mcsend.primary_rc),getSecErrInfo(mcsend.secondary_rc));
return(-1);
}

/* if sending operation is success,and partner lu issue REQUEST_TO_SEND
verb */
/* change local lu state to RECEIVE_AND_WAIT
*/
memset(&mcrec, 0x00, sizeof(mcrec));
mcrec.opcode = AP_M_RECEIVE_AND_WAIT;
mcrec.opext = AP_MAPPED_CONVERSATION;
memcpy(mcrec.tp_id, appcres->tpid, sizeof(appcres->tpid));
mcrec.conv_id = appcres->convid;
mcrec.rtn_status = AP_YES;
mcrec.max_len = *rcvlen;
mcrec.dptr = rcvbuf;

/* proccessing the recving operation */
APPC(&mcrec);
/* check partner lu is want the CONFORMED verb,then DEALLOCATE the
conversation */
if(mcrec.what_rcvd != AP_DATA_COMPLETE_CONFIRM_DEALL
&& mcrec.what_rcvd != AP_DATA_COMPLETE_SEND) {
apperr("sndrcvSna mcrec tp_id [%08X%08X],conv_id [%08X],what_rcvd
unknow [%08X]\n",
dspTpId(mcrec.tp_id),dspTpId(&mcrec.tp_id[4]),mcrec.conv_id,mcrec.what_rcvd);
return(-1);
}

/* check RECEIVE_AND_WAIT verb is process successful */
if(mcrec.primary_rc != AP_OK) {
apperr("sndrcvSna mcrec tp_id [%08X%08X],conv_id [%08X],ErrInfo
[%s][%s]\n",
dspTpId(mcrec.tp_id),dspTpId(&mcrec.tp_id[4]),mcrec.conv_id,getPrmErrInfo(mcrec.primary_rc),getSecErrInfo(mcrec.secondary_rc));
return(-1);
}else {
*rcvlen = mcrec.dlen;
}

return(0);
}

int cfmSna(APPC_RES * appcres)
{
struct mc_confirmed mcconfirmed;

if(appcres == NULL) {
apperr("confirmSna parameter fail!\n");
return(-1);
}

/* prepare the mcconfirmed struct to commit the transation */
memset(&mcconfirmed, 0x00, sizeof(mcconfirmed));
mcconfirmed.opcode = AP_M_CONFIRMED;
mcconfirmed.opext = AP_MAPPED_CONVERSATION;
memcpy( mcconfirmed.tp_id, appcres->tpid, sizeof(appcres->tpid));
mcconfirmed.conv_id = appcres->convid;

/* process the AP_M_CONFIRMED verb */
APPC(&mcconfirmed);
/* check wether the AP_M_CONFIRMED verb process success */
if(mcconfirmed.primary_rc != AP_OK) {
apperr("confirmSna mcconfirmed tp_id [%08X%08X],conv_id
[%08X],ErrInfo [%s][%s]\n",
dspTpId(mcconfirmed.tp_id),dspTpId(&mcconfirmed.tp_id[4]),mcconfirmed.conv_id,getPrmErrInfo(mcconfirmed.primary_rc),getSecErrInfo(mcconfirmed.secondary_rc));
return(-1);
}

/* partner lu already deallocate the conversation,no need to do it
again */
/* appcres->convid = 0; should be control by application */

return(0);
}

int detachSna(APPC_RES * appcres)
{
struct mc_deallocate mcdealloc;
struct tp_ended tpended;

if(appcres == NULL) {
apperr("detachSna parameter fail!\n");
return(-1);
}

if(appcres->convid > 0 && appcres->convid != 0xFFFFFFFF) {
memset(&mcdealloc, 0x00, sizeof(mcdealloc));
mcdealloc.opcode = AP_M_DEALLOCATE;
mcdealloc.opext = AP_MAPPED_CONVERSATION;
memcpy( mcdealloc.tp_id, appcres->tpid, sizeof(appcres->tpid));
mcdealloc.conv_id = appcres->convid;
mcdealloc.dealloc_type = AP_FLUSH;

APPC(&mcdealloc);
appcres->convid = -1;
if(mcdealloc.primary_rc != AP_OK) {
apperr("detachSna mcdealloc tp_id [%08X%08X],conv_id
[%08X],ErrInfo [%s][%s]\n",
dspTpId(mcdealloc.tp_id),dspTpId(&mcdealloc.tp_id[4]),mcdealloc.conv_id,getPrmErrInfo(mcdealloc.primary_rc),getSecErrInfo(mcdealloc.secondary_rc));
}
}

if(appcres->tpid != NULL) {
memset(&tpended, 0x00, sizeof(tpended));
tpended.opcode = AP_TP_ENDED;
memcpy(tpended.tp_id, appcres->tpid, sizeof(appcres->tpid));
APPC(&tpended);

if(tpended.primary_rc != AP_OK) {
apperr("detachSna tpended tp_id [%08X%08X],ErrInfo [%s][%s]\n",
dspTpId(tpended.tp_id),dspTpId(&tpended.tp_id[4]),getPrmErrInfo(tpended.primary_rc),getSecErrInfo(tpended.secondary_rc));
return(-1);
}
}

return(0);

}
Edward Burr
2009-05-13 14:51:30 UTC
Permalink
Post by zhangych
I rewrite a appc program from the CPIC,to change tcpip to sna server from
aix system.when i
close the sna with verb AP_M_DEALLOCATE,AP_AP_ABEND or AP_FLUSH and
AP_TP_ENDED to terminate the session,normally,the both side of session is
closed correct.
But sometime,the session at aix is ok,but at os/390 side,the session is
hungup,and can not stop with command,but the transaction is commit with the
verb AP_M_CONFIRMED.only when i stop the process ,the sesssion hunguped will
free.I found nothing in the /var/sna logfile.
I see in your source code that your app appears to log errors from the
APPC calls (calling a function: apperr) if the primary return code is
anything other that AP_OK. Is anything getting logged?

Loading...