/*----------------------------------------------------------------* |srtp_api.h | |@version: 2.1 | |Last Modification: Oct 1st, 2003 , by Fei | | | |Definition of SRMP API functions | *----------------------------------------------------------------*/ /*----------------------------------------------------------------* | Copyright 2001-2003 Networking and Simulation Laboratory | | George Mason University, Fairfax, Virginia | | | | Permission to use, copy, modify, and distribute this | | software and its documentation for academic purposes is hereby | | granted without fee, provided that the above copyright notice | | and this permission appear in all copies and in supporting | | documentation, and that the name of George Mason University | | not be used in advertising or publicity pertaining to | | distribution of the software without specific, written prior | | permission. GMU makes no representations about the suitability | | of this software for any purposes. It is provided "AS IS" | | without express or implied warranties. All risk associated | | with use of this software is expressly assumed by the user. | *----------------------------------------------------------------*/ #include #ifdef UNIX #include #include #include #include #include #include #include #include #else #include #include #endif #include #define SRMP_VERSION 2 /* the UDP port that a SRMP daemon will listen on for request from local client */ #define REQ_UDP_PORT 8001 #define REQ_HEADER_LEN 28 /* the length of the client request header */ /* SRMP request types */ #define SRMP_INIT 0 #define SRMP_TERM 1 #define SRMP_REGDATAID 2 #define SRMP_DROPDATAID 3 #define SRMP_SEND 4 #define SRMP_SUBDATAID 5 #define SRMP_UNSUBDATAID 6 /* SRMP request lengths */ #define SRMP_TERM_LEN 2 #define SRMP_SUB_UNSUB_DATAID_LEN 20 /* SRMP message types */ #define SRMP_DATA 0 #define SRMP_NAK 1 #define SRMP_ACK 2 #define SRMP_HBEAT 3 /* MAX_M1_MESSAGE_LEN + MESSAGE_HEADER_LEN(28) */ #define MAX_M1_BUFFER_SIZE 131099 /* the message header format for client request */ typedef struct request_t{ unsigned short int version; unsigned short int type; long mca; unsigned int dataid; unsigned int len; unsigned short int mode; unsigned int port; unsigned int ack_port; } request_t; /* function to create socket and bind a system availabe udp port to it */ int create_socket(int * sockfd_return, int * port_return); /* send reqeust to local SRTP daemon */ int send_req(char *send_msg, int len); /* waiting to receive an ACK from local SRTP daemon */ int receive_ack(char * ack_buffer); /* init socket and data structure */ int srmp_init(int udp_port); /* send a request to local SRTP daemon to register a */ int srmp_reg_dataid(unsigned long int mca, int dataid, int mode ); /* send mode1/mode0 message to the SRTP daemon */ int srmp_send(char *data, int len, int dataid, unsigned long int mca); /* send a request to local SRTP daemon to un-register a */ int srmp_unreg_dataid(unsigned long int mca,int dataid); /* send a subscribe request to local SRTP daemon to subscribe a */ int srmp_subscribe_mca(unsigned long int mca); /* waiting to receie a message from local SRTP daemon */ int srmp_recv(char *buf, int *len, int * dataid, unsigned long int * mcg); /* send a un-subscribe request to local SRTP to un-subscribe a */ int srmp_unsubscribe_mca(unsigned long int mca); int srmp_term(); /******************************************************************************/ /* global variable */ /******************************************************************************/ int req_port; char message_buffer[MAX_M1_BUFFER_SIZE]; /* receiving buffer */ char ack_buffer[1024]; /* ack message buffer */ char send_buffer[MAX_M1_BUFFER_SIZE]; /* sending buffer */ struct request_t header; int ack_sock, ack_sock_port; /* the UDP port that client receive ack from */ int sockfd, sock_port; /* the UDP port client receive message from */ /*******************************************************************************/ /* create a UDP socket for communication with SRMP daemon */ /* this function should be called by srmp_init() only */ /* return value equals to 0 indicates the socket was created successfully */ /* sockfd_return is the socket file descriptor */ /* prot_return is the UDP port number binded to the socket */ /*******************************************************************************/ int create_socket(int * sockfd_return, int * port_return) { int socket_fd; int port; sockaddr_in a; port=10000; a.sin_family = AF_INET; a.sin_addr.s_addr = htonl(INADDR_LOOPBACK); a.sin_port = htons(port); #ifndef UNIX WSAData wsaData; if( WSAStartup(0x101,&wsaData)) fprintf(stderr, "Unable to initialize WinSock library.\n"); #endif /* create the socket */ socket_fd= socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP); if( socket_fd<0) { fprintf(stderr,"**Invalid socket**\n"); exit(-1); } /* try bind the socket with a free port number */ while( bind(socket_fd,(sockaddr *)&a,sizeof(a)) < 0 && port<65536 ) { port++; a.sin_port = htons(port); } if(port<65536) { *sockfd_return=socket_fd; *port_return=port; return 0; } else return -1; } /**************************************************************************/ /* each time the client send a request to the SRMP daemon, the client */ /* will wait for an ACK from the SRMP daemon, to indicate the result */ /* of the request */ /**************************************************************************/ int receive_ack(char * ack_buffer) { struct sockaddr from; int recv_data_len; int sockaddr_len=sizeof(from); /* receive from the SRMP daemon */ recv_data_len = recvfrom(ack_sock, ack_buffer, 40, 0, &from, &sockaddr_len); return recv_data_len; } /****************************************************/ /* send request to local SRMP daemon through socket */ /****************************************************/ int send_req(char *send_msg, int len) { int send_len; sockaddr_in local_srmp; char buf[500]; int ack_len; int value; memset(&local_srmp, 0, sizeof(local_srmp)); local_srmp.sin_family = AF_INET; local_srmp.sin_addr.s_addr = inet_addr("127.0.0.1"); local_srmp.sin_port= htons(req_port); /* send the client request to the SRMP daemon through socket */ send_len=sendto(ack_sock, send_msg, len, 0, (struct sockaddr *) &local_srmp, sizeof(local_srmp)); /* receive ACK message from local SRMP daemon */ ack_len=receive_ack(buf); if(send_len>0 && ack_len>0) { value = atoi(&(buf[0])); return value; } else return -1; } /************************************************************************/ /* initialize sockets for client to communicate with local SRMP daemon */ /************************************************************************/ int srmp_init(int udp_port) { int result=0; char *msg; long bufsz = 65536; unsigned long int sock_buff_len; if(udp_port==0) req_port=REQ_UDP_PORT; else req_port=udp_port; /* create the socket for receiving message from the SRTP daemon */ create_socket(&sockfd, &sock_port); /* create the socket for sending request to and receiving ACK * from the SRTP daemon */ create_socket(&ack_sock, &ack_sock_port); /* increate the socket sending and receiving buffer size */ sock_buff_len=0xFFFF; setsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, (const char *)&sock_buff_len, sizeof(sock_buff_len)); sock_buff_len=0xFFFF; if(setsockopt(sockfd, SOL_SOCKET, SO_RCVBUF, (const char *)&sock_buff_len, sizeof(sock_buff_len)) <0) { printf("set socket option error\a\n"); exit(-1); } msg = (char*)malloc(REQ_HEADER_LEN); if (!msg) return(-1); /* send SRMP_INIT request to the SRMP daemon */ header.version=SRMP_VERSION; header.type=SRMP_INIT; header.ack_port=ack_sock_port; memcpy(msg, &header, REQ_HEADER_LEN); result = send_req(msg, REQ_HEADER_LEN); free(msg); return result; } /************************************************************/ /* int srmp_send(): builds the packets and appends the data */ /************************************************************/ int srmp_send(char *data, int len, int dataid, unsigned long int mca) { int result; /* check length */ if((len < 0)) return(-1); /* compose the SRMP_SEND request */ header.version=SRMP_VERSION; header.type=SRMP_SEND; header.mca=mca; header.dataid=dataid; header.port=sock_port; header.ack_port=ack_sock_port; header.len=len; memcpy(send_buffer, &header, REQ_HEADER_LEN); /* copy data into the request */ memcpy(send_buffer+REQ_HEADER_LEN, data, len); result = send_req(send_buffer,REQ_HEADER_LEN+len); return result; } /************************************************************/ /* register at local SRMP daemon */ /************************************************************/ int srmp_reg_dataid(unsigned long int mca, int dataid, int mode ) { char *msg; int result; if(mode==0) return 0; msg = (char*)malloc(REQ_HEADER_LEN); if (!msg) return(-1); header.version=SRMP_VERSION; header.type=SRMP_REGDATAID; header.mca=mca; header.dataid=dataid; header.mode=mode; header.ack_port=ack_sock_port; memcpy(msg, &header, REQ_HEADER_LEN); result = send_req(msg, REQ_HEADER_LEN); free(msg); return result; } /*******************************************************/ /* un-register a at local SRMP daemon */ /*******************************************************/ int srmp_unreg_dataid(unsigned long int mca,int dataid) { char *msg; int result; msg = (char*)malloc(REQ_HEADER_LEN); if (!msg) return(-1); header.version=SRMP_VERSION; header.type=SRMP_DROPDATAID; header.mca=mca; header.dataid=dataid; header.ack_port=ack_sock_port; memcpy(msg, &header, REQ_HEADER_LEN); result = send_req(msg, REQ_HEADER_LEN); free(msg); return result; } /********************/ /* subscribe a mca */ /********************/ int srmp_subscribe_mca(unsigned long int mca) { char *msg; int result; /* compose the SRMP_SUBDATAID request */ header.mca=mca; header.port=sock_port; header.ack_port=ack_sock_port; header.version=SRMP_VERSION; header.type=SRMP_SUBDATAID; msg = (char*)malloc(REQ_HEADER_LEN); if (!msg) return(-1); memcpy(msg, &header, REQ_HEADER_LEN); /* send request to local SRMP daemon */ result = send_req(msg, REQ_HEADER_LEN); free(msg); return result; } /**********************/ /* unsubscribe a mca */ /**********************/ int srmp_unsubscribe_mca(unsigned long int mca) { char *msg; int result; /* compose the SRMP_UNSUBDATAID message */ header.mca=mca; header.port=sock_port; header.ack_port=ack_sock_port; header.version=SRMP_VERSION; header.type=SRMP_UNSUBDATAID; msg = (char*)malloc(REQ_HEADER_LEN); if(!msg) return(-1); memcpy(msg, &header, REQ_HEADER_LEN); /* send the request to local SRMP daemon */ result = send_req(msg, REQ_HEADER_LEN); free(msg); return result; } /********************************************/ /* receive a message from local SRMP daemon */ /********************************************/ int srmp_recv(char *buf, int *len, int * dataid, unsigned long int * mcg) { short recv_data_len; struct sockaddr from; int sockaddr_len=sizeof(from); unsigned long int mca; /* receive a message from local SRMP daemon */ recv_data_len = recvfrom(sockfd, message_buffer, 128000, 0, &from, &sockaddr_len); *len = recv_data_len-6; /* parse the dataid */ unsigned char high_byte, low_byte; memcpy(&high_byte, message_buffer, 1); memcpy(&low_byte, message_buffer+1, 1); *dataid=(int)high_byte*256+(int)low_byte; /* parse the mca */ memcpy(&mca, message_buffer+2, sizeof(unsigned long int )); *mcg=mca; /* copy the message body */ memcpy(buf, message_buffer+6, recv_data_len-6); return(recv_data_len); } /***********************/ /* terminate the client */ /***********************/ int srmp_term() { char *msg; int result; msg = (char*)malloc(SRMP_TERM_LEN); if (!msg) return(-1); msg[0] = SRMP_VERSION; msg[1] = SRMP_TERM; result = send_req(msg, SRMP_TERM_LEN); free(msg); return result; }