?? cmppbuild.c
字號:
/*******************************************************
NAME: cmppbuild.c
PURPOSE: China Mobile Peer to Peer Protocol 2.0
Permanent connection implementation to
submit data to Internet Short Message Gateway
or deliver data from ISMG to upper layer.
automatically building TCP connection implementation.
VERSION: 0.0.1
AUTHOR: Ke Heng Zhong
DATE: 2002/06/17 12:52
MODIFIED: 2000/06/17 21:12
********************************************************/
#include "kevopsall.ext"
#include "cmpp.h"
int cmcon_get_unique_id()
{
static int carcid = 0;
if (++carcid == 0) ++carcid;
return carcid;
}
int cmpp_build_conn (VTASK * entity, void * userInfo)
{
CmppEntity * cment = NULL;
CmppCon * cmcon = NULL;
VTASK * vtask = NULL;
SPCMPP * spc = NULL;
int addrlen;
struct sockaddr_in sock;
int fd = -1;
int connsucc = 0;
/* current vtask is the entity */
#ifdef _DEBUG
info("cmpp_build_conn: building connection hook started.\n");
#endif
if (!entity) return 0;
cment = (CmppEntity *) entity->var;
spc = (SPCMPP *)entity->cvopsState->ref;
#ifdef _DEBUG
info("cmpp_build_conn: non-block connect %s:%d\n",
cment->remote_host, cment->remote_port);
#endif
cment->remote_port, &connsucc);
if (connsucc > 0) {
#ifdef _DEBUG
info("cmpp_build_conn: non-block connect returned connsucc:%d\n", connsucc);
#endif
vtask = getFirstFreeConnection(entity);
if (!vtask) {
error("cmpp_build_conn: not enough virtual task.\n");
close(fd);
startTimer(entity, t_build, TBUILD);
return 0;
}
cmcon = (CmppCon *) vtask->var;
cmcon->fd = fd;
addrlen = sizeof(sock);
if (getpeername(fd, (struct sockaddr *)&sock, &addrlen) == 0) {
cment->remote_ip = sock.sin_addr;
cmcon->remote_ip = sock.sin_addr;
cmcon->remote_port = sock.sin_port;
} else {
error("cmpp_build_conn: can't get peer address.\n");
close(fd);
cmcon->fd = -1;
checkIdleConnection(vtask);
startTimer(entity, t_build, TBUILD);
return 0;
}
addrlen = sizeof(sock);
if (getsockname(fd, (struct sockaddr *)&sock, &addrlen) == 0) {
cmcon->local_ip = sock.sin_addr;
cmcon->local_port = sock.sin_port;
} else {
cmcon->local_ip.s_addr = 0;
cmcon->local_port = 0;
}
if (sk_num(cment->init_list) < cment->mt_num) {
/* the connection is for CMPP MT connection */
cmcon->is_mo = 0;
cmcon->version = ((uint8)spc->mtmajorver << 4) & 0xF0;
cmcon->version |= ((uint8)spc->mtminorver & 0x0F);
/*cmcon->version = (((uint8)getConfInt ("General", "MTMajor_Version")) << 4) & 0xF0;;
cmcon->version |= ((uint8)getConfInt("General","MTMinor_Version") & 0x0F);*/
} else if (sk_num(cment->mo_list) < cment->mo_num) {
/* the connection is for CMPP MO connection */
cmcon->is_mo = 1;
cmcon->version = ((uint8)spc->momajorver << 4) & 0xF0;;
cmcon->version |= ((uint8)spc->mominorver & 0x0F);
/*cmcon->version = (((uint8)getConfInt ("General", "MOMajor_Version")) << 4) & 0xF0;;
cmcon->version |= ((uint8)getConfInt("General","MOMinor_Version") & 0x0F);*/
} else {
error("CMPP Connection number is exceeded. Now new built connection tearing down.\n");
closesocket(fd);
cmcon->fd = -1;
vtask->state = cmpp_null;
checkIdleConnection(vtask);
return 0;
}
/* send CMPP connect PDU to ISMG */
if (send_cmpp_connect (vtask) < 0) {
error("cmpp_build_conn: TCP connection crashed while sending CMPP Connect.\n");
vtask->state = cmpp_null;
close(fd);
cmcon->fd = -1;
checkIdleConnection(vtask);
startTimer(entity, t_build, TBUILD);
return 0;
}
cmcon->devid = enterLongDevice(
entity->cvopsState,
vtask,
fd,
DF_READ,
cmpp_data_recv,
NULL,
"cmcon_init_recv");
if (cmcon->devid == -1) {
error("cmpp_build_conn: I/O device number exceeded.\n");
close(fd);
cmcon->fd = -1;
checkIdleConnection(vtask);
startTimer(entity, t_build, TBUILD);
return 0;
}
cmcon->conid = cmcon_get_unique_id();
vtask->state = cmpp_handshaking;
#ifdef _DEBUG
info("cmcon_build_conn: entity %s allocated conid %d.\n",
entity->name, cmcon->conid);
#endif
tolog("CMPP SP TCP connect to %s:%d successfully from %s.\n",
inet_ntoa(cmcon->remote_ip), cmcon->remote_port, vtask->name);
return 0;
}
else { /* non-blocking connect operation unsuccessfully */
#ifdef _DEBUG
info("cmpp_build_conn: non-block connect not successfully, "
"returned connsucc:%d\n", connsucc);
#endif
if (fd != -1) {
#ifdef _DEBUG
info("cmpp_build_conn: non-block socket created, but connection coming later.\n");
#endif
/* socket create successfully, but connection is ready later */
vtask = getFirstFreeConnection(entity);
if (!vtask) {
error("cmpp_build_conn: not enough virtual task for non-blocking.\n");
close(fd);
startTimer(entity, t_build, TBUILD);
return 0;
}
cmcon = (CmppCon *) vtask->var;
cmcon->fd = fd;
cmcon->devid = enterLongDevice(
entity->cvopsState,
vtask,
fd,
DF_WRITE,
cmpp_conn_succ,
NULL,
"cmpp_non_blocking");
if (cmcon->devid == -1) {
error("cmpp_build_conn: I/O device number exceeded for non-blocking.\n");
close(fd);
cmcon->fd = -1;
checkIdleConnection(vtask);
startTimer(entity, t_build, TBUILD);
return 0;
}
#ifdef _DEBUG
info("cmpp_build_conn: one not-ready connection"
" vtask %s for reserving.\n", vtask->name);
#endif
return 0;
} else { /* connect failed */
error("cmpp_build_conn: non-block connect"
" failed completely, start t_build.\n");
startTimer(entity, t_build, TBUILD);
}
}
return 0;
}
void cmpp_conn_succ (VTASK * vtask, int fd, unsigned event)
{
VTASK * entity = NULL;
CmppCon * cmcon = NULL;
CmppEntity * cment = NULL;
SPCMPP * spc = NULL;
int addrlen;
struct sockaddr_in sock;
#ifdef UNIX
int sockerr, sockerrlen, retval;
#endif
if (!vtask || fd == -1 || event != DF_WRITE)
return;
#ifdef _DEBUG
info("cmpp_conn_succ: connect event started.\n");
#endif
spc = (SPCMPP *)vtask->cvopsState->ref;
cmcon = (CmppCon *)vtask->var;
entity = (VTASK *) getEntity (vtask);
cment = (CmppEntity *)entity->var;
if (!cmcon || !cment) {
error("cmpp_conn_succ: internal error.\n");
vtask->state = cmpp_null;
checkIdleConnection(vtask);
startTimer(entity, t_build, TBUILD);
return;
}
if (cmcon->fd != fd) {
error("cmpp_conn_succ: non-blocking connection succ indication is invalid.\n");
close(fd);
vtask->state = cmpp_null;
checkIdleConnection(vtask);
if (cmcon->is_mo)
sk_delete_ptr(cment->mo_list, vtask);
else
sk_delete_ptr(cment->init_list, vtask);
startTimer(entity, t_build, TBUILD);
return;
}
#ifdef UNIX
sockerrlen = sizeof(int);
sockerr = 0;
retval = getsockopt(fd, SOL_SOCKET, SO_ERROR, &sockerr, &sockerrlen);
if (retval < 0 || sockerr != 0) {
error("cmpp_conn_succ: %s.\n",
retval < 0 ? "getsockopt error":"non-blocking unsuccessfully!");
removeDevice(vtask->cvopsState, cmcon->devid);
cmcon->devid = -1;
closesocket(cmcon->fd);
cmcon->fd = INVALID_SOCKET;
vtask->state = cmpp_null;
checkIdleConnection(vtask);
if (cmcon->is_mo)
sk_delete_ptr(cment->mo_list, vtask);
else
sk_delete_ptr(cment->init_list, vtask);
startTimer(entity, t_build, TBUILD);
return;
}
#endif
removeDevice(vtask->cvopsState, cmcon->devid);
cmcon->devid = -1;
addrlen = sizeof(sock);
if (getpeername(fd, (struct sockaddr *)&sock, &addrlen) == 0) {
cment->remote_ip = sock.sin_addr;
cmcon->remote_ip = sock.sin_addr;
cmcon->remote_port = sock.sin_port;
} else {
error("cmpp_conn_succ: can't get peer address.\n");
close(cmcon->fd);
cmcon->fd = -1;
vtask->state = cmpp_null;
checkIdleConnection(vtask);
if (cmcon->is_mo)
sk_delete_ptr(cment->mo_list, vtask);
else
sk_delete_ptr(cment->init_list, vtask);
startTimer(entity, t_build, TBUILD);
return;
}
addrlen = sizeof(sock);
if (getsockname(fd, (struct sockaddr *)&sock, &addrlen) == 0) {
cmcon->local_ip = sock.sin_addr;
cmcon->local_port = sock.sin_port;
} else {
cmcon->local_ip.s_addr = 0;
cmcon->local_port = 0;
}
if (sk_num(cment->init_list) < cment->mt_num) {
/* the connection is for CMPP MT connection */
cmcon->is_mo = 0;
cmcon->version = ((uint8)spc->mtmajorver << 4) & 0xF0;
cmcon->version |= ((uint8)spc->mtminorver & 0x0F);
/*cmcon->version = (((uint8)getConfInt ("General", "MTMajor_Version")) << 4) & 0xF0;;
cmcon->version |= ((uint8)getConfInt("General","MTMinor_Version") & 0x0F);*/
} else if (sk_num(cment->mo_list) < cment->mo_num) {
/* the connection is for CMPP MO connection */
cmcon->is_mo = 1;
cmcon->version = ((uint8)spc->momajorver << 4) & 0xF0;;
cmcon->version |= ((uint8)spc->mominorver & 0x0F);
/*cmcon->version = (((uint8)getConfInt ("General", "MOMajor_Version")) << 4) & 0xF0;;
cmcon->version |= ((uint8)getConfInt("General","MOMinor_Version") & 0x0F);*/
} else {
error("CMPP Connection number is exceeded. Now new built connection tearing down.\n");
closesocket(fd);
cmcon->fd = -1;
vtask->state = cmpp_null;
checkIdleConnection(vtask);
return;
}
/* send CMPP connect PDU to ISMG */
if (send_cmpp_connect (vtask) < 0) {
error("cmpp_build_conn: TCP connection crashed while sending CMPP Connect.\n");
vtask->state = cmpp_null;
close(fd);
cmcon->fd = -1;
checkIdleConnection(vtask);
startTimer(entity, t_build, TBUILD);
return;
}
cmcon->devid = enterLongDevice(
vtask->cvopsState,
vtask,
fd,
DF_READ,
cmpp_data_recv,
NULL,
"cmcon_init_recv");
if (cmcon->devid == -1) {
error("cmpp_conn_succ: I/O device number exceeded.\n");
close(fd);
cmcon->fd = -1;
vtask->state = cmpp_null;
checkIdleConnection(vtask);
if (cmcon->is_mo)
sk_delete_ptr(cment->mo_list, vtask);
else
sk_delete_ptr(cment->init_list, vtask);
startTimer(entity, t_build, TBUILD);
return;
}
cmcon->conid = cmcon_get_unique_id();
#ifdef _DEBUG
info("cmpp_conn_succ: alloc connection id:%d.\n", cmcon->conid);
#endif
vtask->state = cmpp_handshaking;
tolog("CMPP SP TCP connect to %s:%d successfully from %s.\n",
inet_ntoa(cmcon->remote_ip), cmcon->remote_port, vtask->name);
checkIdleConnection(vtask);
return;
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -