| #include <errno.h> |
| #include <stdlib.h> |
| #include <strings.h> |
| #include <sys/types.h> |
| #include <sys/socket.h> |
| #include <netinet/tcp.h> |
| #include <stdio.h> |
| #include <arpa/inet.h> |
| #include <unistd.h> |
| #include <ifaddrs.h> |
| #include <net/if.h> |
| #include <string.h> |
| #include <sys/un.h> |
| |
| #define SERVERNAME "/tmp/socket-demoapp" |
| #define STARTKEEPALIVE "RIL_REQUEST_START_KEEPALIVE_PRO" |
| #define STOPKEEPALIVE "RIL_REQUEST_STOP_KEEPALIVE_PRO" |
| #define KEEPALIVESTATUS "RIL_UNSOL_KEEPALIVE_STATUS_PRO" |
| |
| typedef enum { |
| IPV4_TCP = 0, |
| IPV4_UDP = 1, |
| IPV6_TCP = 2, |
| IPV6_UDP = 3 |
| } PacketType; |
| |
| #define MAX_INADDR_LEN 16 |
| typedef struct { |
| PacketType type; /* Type of keepalive packet */ |
| char sourceAddress[MAX_INADDR_LEN]; /* Source address in network-byte order */ |
| int sourcePort; /* Source port if applicable, or 0x7FFFFFFF; |
| the maximum value is 65535 */ |
| char destinationAddress[MAX_INADDR_LEN]; /* Destination address in network-byte order */ |
| int destinationPort; /* Destination port if applicable or 0x7FFFFFFF; |
| the maximum value is 65535 */ |
| int netif_id; |
| int keepIdleTime; /*Sec. If no data during these time, start detecting, */ |
| int keepIntervalTime; /*seconds between two packets*/ |
| int retryCount; /*Detecting counts*/ |
| } Keepalive_Pro; |
| |
| typedef enum{ |
| KEEPALIVE_ACTIVE, |
| KEEPALIVE_INACTIVE, |
| KEEPALIVE_PENDING |
| } KeepaliveStatusCode; |
| |
| typedef struct{ |
| uint32_t sessionHandle; |
| KeepaliveStatusCode code; |
| } KeepaliveStatus; |
| |
| |
| int TCPkeepaliveonoff(int sockfd,int onoff,Keepalive_Pro *KLpro) |
| { |
| setsockopt(sockfd, SOL_TCP, TCP_KEEPCNT, &(KLpro->retryCount), sizeof(KLpro->retryCount)); |
| setsockopt(sockfd, SOL_TCP, TCP_KEEPIDLE, &(KLpro->keepIdleTime), sizeof(KLpro->keepIdleTime)); |
| setsockopt(sockfd, SOL_TCP, TCP_KEEPINTVL, &(KLpro->keepIntervalTime), sizeof(KLpro->keepIntervalTime)); |
| setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, &onoff, sizeof(onoff)); |
| } |
| |
| int createsock(char *serverip,int server_port) |
| { |
| int clientSocket; |
| struct sockaddr_in serverAddr; |
| if((clientSocket = socket(AF_INET, SOCK_STREAM, 0)) < 0) |
| { |
| printf("create socket error"); |
| return 1; |
| } |
| |
| serverAddr.sin_family = AF_INET; |
| serverAddr.sin_port = htons(server_port); |
| serverAddr.sin_addr.s_addr = inet_addr(serverip); |
| if(connect(clientSocket, (struct sockaddr *)&serverAddr, sizeof(serverAddr)) < 0) |
| { |
| printf("connect to server error"); |
| return 1; |
| } |
| return clientSocket; |
| |
| } |
| |
| int getipif(char* ip,char *iface) |
| { |
| struct ifaddrs *addrs, *iap; |
| struct sockaddr_in *sa; |
| char buf[32]; |
| |
| getifaddrs(&addrs); |
| for (iap = addrs; iap != NULL; iap = iap->ifa_next) |
| { |
| if (iap->ifa_addr && (iap->ifa_flags & IFF_UP) && iap->ifa_addr->sa_family == AF_INET) |
| { |
| sa = (struct sockaddr_in *)(iap->ifa_addr); |
| inet_ntop(iap->ifa_addr->sa_family, (void *)&(sa->sin_addr), buf, sizeof(buf)); |
| if (!strcmp(ip, buf)) |
| { |
| strcpy(iface,iap->ifa_name); |
| } |
| } |
| } |
| freeifaddrs(addrs); |
| return 0; |
| } |
| |
| int printsockinfo(int sockfd) |
| { |
| struct sockaddr_in local_addr; |
| char local_ip[MAX_INADDR_LEN]; |
| int local_port=0; |
| char iface[10]; |
| socklen_t local_addr_len=sizeof(local_addr); |
| getsockname(sockfd,(struct sockaddr *)&local_addr,&local_addr_len); |
| inet_ntop(AF_INET,&local_addr.sin_addr,local_ip,sizeof(local_ip)); |
| local_port=ntohs(local_addr.sin_port); |
| getipif(local_ip,iface); |
| printf("local ip %s port %d interface %s\n",local_ip,local_port,iface); |
| } |
| |
| int getKLpara(int sockfd,Keepalive_Pro *KLpro) |
| { |
| struct sockaddr_in source_addr; |
| |
| char iface[10]; |
| socklen_t source_addr_len=sizeof(source_addr); |
| getsockname(sockfd,(struct sockaddr *)&source_addr,&source_addr_len); |
| //get source ip |
| inet_ntop(AF_INET,&source_addr.sin_addr,KLpro->sourceAddress,sizeof(KLpro->sourceAddress)); |
| //get source port |
| KLpro->sourcePort=ntohs(source_addr.sin_port); |
| |
| getipif(KLpro->sourceAddress,iface); |
| if(strstr(iface,"ccmni")) |
| { |
| KLpro->netif_id=atoi(iface+5); |
| } |
| printf(" ip %s port %d interface %s\n",KLpro->sourceAddress,KLpro->sourcePort,iface); |
| } |
| |
| |
| int sendinfotoserver(int sockfd) |
| { |
| int ret=0; |
| ret=send(sockfd,"\0",1,0); |
| if(ret<=0) |
| { |
| printf("send info to server error\n"); |
| return -1; |
| } |
| printf("send info to server\n"); |
| return 0; |
| } |
| |
| int setkeepaliveenable(int *sockfd,Keepalive_Pro *KLpro) |
| { |
| int sessionhandle=0; |
| struct sockaddr_un client; |
| //create unix domain socket to connection demoapp |
| *sockfd = socket(AF_UNIX,SOCK_STREAM,0); |
| |
| client.sun_family = AF_UNIX; |
| strcpy(client.sun_path,SERVERNAME); |
| bind(*sockfd,(struct sockaddr *)&client,sizeof(client)); |
| |
| int result = 0; |
| result = connect(*sockfd,(struct sockaddr *)&client,sizeof(client)); |
| if(result <0){ |
| printf("error in connect to demoapp\n"); |
| return 0; |
| } |
| char buf[256]; |
| memset(buf,0,sizeof(buf)); |
| snprintf(buf,256,"%s,%d,%s,%d,%s,%d,%d,%d,%d,%d", |
| STARTKEEPALIVE, |
| 0, |
| KLpro->sourceAddress, |
| KLpro->sourcePort, |
| KLpro->destinationAddress, |
| KLpro->destinationPort, |
| KLpro->netif_id, |
| KLpro->keepIdleTime, |
| KLpro->keepIntervalTime, |
| KLpro->retryCount); |
| printf("send buf %s\n",buf); |
| if( write(*sockfd,buf,sizeof(buf))>0) |
| { |
| printf("send buf to demoapp\n"); |
| } |
| int ret=0; |
| memset(buf,0,sizeof(buf)); |
| if( ret=read(*sockfd,buf,256) >0) |
| { |
| printf("recv buf %s\n",buf); |
| if(strstr(buf,STARTKEEPALIVE)) |
| { |
| if(strstr(buf,"ok")) |
| { |
| char *newbuf=buf+sizeof(STARTKEEPALIVE)+3; |
| char *p=strtok(newbuf,","); |
| char *q=strtok(NULL,","); |
| sessionhandle=atoi(p); |
| printf("code is %s\n",q); |
| } |
| else |
| { |
| return -1; |
| } |
| } |
| } |
| else |
| { |
| printf("read buf from demoapp fail\n"); |
| return -1; |
| } |
| printf("sessionhandle is %d\n",sessionhandle); |
| return sessionhandle; |
| } |
| int keepalivestatuswait(int clientfd) |
| { |
| char buf[256]; |
| int ret; |
| while(1) |
| { |
| memset(buf,0,256); |
| if( (ret=read(clientfd,buf,256)) >0) |
| { |
| buf[ret]='\0'; |
| printf("recv buf %s\n",buf); |
| if(strstr(buf,KEEPALIVESTATUS)) |
| { |
| char *newbuf=buf+sizeof(KEEPALIVESTATUS); |
| printf("newbuf %s\n",newbuf); |
| char *p=strtok(newbuf,","); |
| char *q=strtok(NULL,","); |
| int sessionhandle=atoi(p); |
| int code= atoi(q); |
| printf("code is %d\n",code); |
| if(code==KEEPALIVE_INACTIVE) |
| { |
| printf("keepalive is fail\n"); |
| break; |
| } |
| } |
| } |
| |
| } |
| return 0; |
| } |
| int setkeepalivedisable(int sessionhandle) |
| { |
| |
| struct sockaddr_un client; |
| //create unix domain socket to connection demoapp |
| int sockfd = socket(AF_UNIX,SOCK_STREAM,0); |
| |
| client.sun_family = AF_UNIX; |
| strcpy(client.sun_path,SERVERNAME); |
| bind(sockfd,(struct sockaddr *)&client,sizeof(client)); |
| |
| int result = 0; |
| result = connect(sockfd,(struct sockaddr *)&client,sizeof(client)); |
| if(result <0){ |
| return 0; |
| } |
| |
| char buf[256]; |
| memset(buf,0,sizeof(buf)); |
| snprintf(buf,256,"%s,%d", |
| STOPKEEPALIVE, |
| sessionhandle); |
| if( write(sockfd,buf,sizeof(buf))>0) |
| { |
| printf("send buf to demoapp"); |
| } |
| |
| int ret=0; |
| memset(buf,0,sizeof(buf)); |
| if( ret=read(sockfd,buf,256) >0) |
| { |
| printf("recv buf %s\n",buf); |
| if(strstr(buf,STOPKEEPALIVE)) |
| { |
| if(strstr(buf,"ok")) |
| { |
| printf("stop keepalive ok\n"); |
| } |
| else |
| { |
| return -1; |
| printf("stop keepalive fail\n"); |
| } |
| } |
| } |
| return 0; |
| } |
| |
| int main(int argc,char *argv[]) |
| { |
| |
| if(argc<3) |
| { |
| printf("keepalivedemo 1 destinationAddress destinationPort keepIdleTime keepIntervalTime retryCount\n"); |
| |
| printf("keepalivedemo 0 sessionhandle\n"); |
| return 0; |
| } |
| printf("argv %s %s \n",argv[1],argv[2]); |
| if(atoi(argv[1])==1) |
| { |
| Keepalive_Pro KLdemo; |
| strcpy(KLdemo.destinationAddress,argv[2]); |
| KLdemo.destinationPort=atoi(argv[3]); |
| if(argv[4]!=NULL) |
| KLdemo.keepIdleTime=atoi(argv[4]); |
| if(argv[5]!=NULL) |
| KLdemo.keepIntervalTime=atoi(argv[5]); |
| if(argv[6]!=NULL) |
| KLdemo.retryCount=atoi(argv[6]); |
| |
| //create socket connect to destinationAddress |
| int sockfd=createsock(KLdemo.destinationAddress,KLdemo.destinationPort); |
| |
| #if DEBUG |
| TCPkeepaliveonoff(sockfd,1,&KLdemo); |
| #endif |
| |
| //get keepalive parameter |
| getKLpara(sockfd,&KLdemo); |
| |
| //set keepalive enable to MD |
| int clientfd; |
| int sessionhandle=setkeepaliveenable(&clientfd,&KLdemo); |
| |
| //send a data to server to ensure MD get the information for keepalive |
| sendinfotoserver(sockfd); |
| |
| //MD do keepalive,wait infomation |
| keepalivestatuswait(clientfd); |
| |
| close(clientfd); |
| close(sockfd); |
| |
| return 0; |
| } |
| else if(atoi(argv[1])==0) |
| { |
| setkeepalivedisable(atoi(argv[2])); |
| return 0; |
| } |
| } |
| |