/****************************************************************/ /* RTP Implementation Program */ /* Version 9.0.1 */ /* Designed By Ying Min */ /* Last Update: 2007-3-19 */ /****************************************************************/ #include "./include/rtp_pub.h" #include "./include/rtp.h" #include "./include/rtp_const.h" #include "./include/rtp_def.h" #include "./include/rtp_struct.h" #include "./include/rtp_msg.h" int rtp_get_local_ip(void) { struct hostent *host; char hostName[64]; char hostIp[32]; if (gethostname(hostName, 50) == -1) { printf("RTP gethostname fail!\n"); exit(3); } if ((host = gethostbyname(hostName)) == NULL) { printf("RTP gethostbyname fail!\n"); exit(4); } else { sprintf(hostIp, "%d.%d.%d.%d", (BYTE)host->h_addr_list[0][0], (BYTE)host->h_addr_list[0][1], (BYTE)host->h_addr_list[0][2], (BYTE)host->h_addr_list[0][3]); rtpHostIp = inet_addr(hostIp); // Network byte order host_ip, like 0xE60012AC printf("RTP host IP: %s (0x%lX)\n", hostIp, rtpHostIp); } return 0; } void rtp_init(void) { WORD i; printf("RTP Init Start!\n"); rtp_get_local_ip(); memset((BYTE *) rtpSap, 0, sizeof(RTP_SAP) * RTP_MAX_NUM_OF_SAP); memset((BYTE *) rtpPort, 0, RTP_MAX_NUM_OF_PORT / 8); memset((BYTE *) rtpHdlPort, 0, sizeof(RTP_PORT) * RTP_MAX_NUM_OF_PORT); memset((BYTE *) rtpHdlPortFd, -1, sizeof(int) * RTP_MAX_NUM_OF_PORT); for (i = 0; i < RTP_MAX_NUM_OF_PORT; i++) rtpHdlPort[i].fd = -1; rtpHdlPortSelect = 0; rtpPortSelect = 0; RTP_BASE_UDP_PORT = RTP_BASE_UDP_PORT_CONST; /* { FILE *fp=NULL; unsigned short base_port=25000; char s[80]=""; fp = fopen("./conf/rtp.conf","r"); if(fp != NULL) { while(fgets(s,1024,fp) !=(char *)0) { if( (int *)strchr(s,'#') !=NULL) continue; if( !strlen(s) ) continue; if(strncasecmp(s,"base port=",10)==0) { base_port = atoi(&s[10]); if(base_port>1000 && base_port<32768) RTP_BASE_UDP_PORT = base_port; else break; } else break; } fclose(fp); } } */ printf("RTP Init Complete!\n"); } // Called every 10 ms void rtp_timer(void) { rtp_recv_udp_msg(); } void rtp_sap_init(BYTE sapIndex) { memset((BYTE *) &rtpSap[sapIndex], 0, sizeof(RTP_SAP)); } void rtp_port_init(WORD port) { memset((BYTE *) &rtpHdlPort[port], 0, sizeof(RTP_PORT)); rtpHdlPort[port].fd = -1; rtpHdlPortFd[port] = -1; } int rtp_init_udp_socket(struct sockaddr_in saddr, int multicast) { int sock; long sockBuf = 40*1024; int on = 1, timeout = 20; sock = socket(AF_INET, SOCK_DGRAM, 0); if (sock < 0) { fprintf(stderr, "Socket() failed\n"); return -3; } if (setsockopt(sock, SOL_SOCKET, SO_RCVBUF, &sockBuf, sizeof(sockBuf)) != 0) { fprintf(stderr, "RTP set socket buffer failed\n"); return -4; } if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on,sizeof(on)) != 0) { fprintf(stderr, "RTP set addr reusable failed\n"); return -5; } if (setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, &timeout, sizeof(timeout)) != 0) { fprintf(stderr, "RTP set keepalive failed\n"); return -6; } if (fcntl(sock, F_SETFL, O_NONBLOCK) < 0) { fprintf(stderr, "RTP set nonblock failed\n"); return -7; } if (bind(sock, (struct sockaddr *) &saddr, sizeof(struct sockaddr)) < 0) { fprintf(stderr, "RTP binding failed, port: %d\n", htons(saddr.sin_port)); close(sock); return -2; } return sock; } int rtp_init_socket(WORD hdlPort, WORD udpPort) { struct sockaddr_in sinAddr; int fd; memset(&sinAddr, 0, sizeof(struct sockaddr)); sinAddr.sin_family = AF_INET; sinAddr.sin_port = htons(udpPort); sinAddr.sin_addr.s_addr = rtpHostIp; // INADDR_ANY; memset(&(sinAddr.sin_zero), 0, 8); fd = rtp_init_udp_socket(sinAddr, 0); if (fd < 0) { printf("RTP UDP Socket(%d) failed\n", udpPort); return -1; } rtpHdlPort[hdlPort].fd = fd; rtpHdlPortFd[hdlPort] = fd; return 0; } int rtp_get_udp_port(WORD hdlPort) { WORD port = rtpPortSelect; WORD i, index1, index2; for (i = 0; i < RTP_MAX_NUM_OF_PORT; i++) { index1 = port / 32; index2 = port % 32; if (((rtpPort[index1] >> index2) & 1) == 1) { if (++port >= RTP_MAX_NUM_OF_PORT) port = 0; continue; } if (rtp_init_socket(hdlPort, port * 2 + RTP_BASE_UDP_PORT) < 0) return -1; rtpPort[index1] |= 1 << index2; rtpPortSelect = (port + 1) & RTP_MAX_NUM_OF_PORT_1; rtpHdlPort[hdlPort].rtpPort = port; return port; } return -1; } int rtp_release_udp_port(WORD hdlPort) { WORD port = rtpHdlPort[hdlPort].rtpPort; int fd = rtpHdlPort[hdlPort].fd; WORD index1, index2; if (port >= RTP_MAX_NUM_OF_PORT) return -1; index1 = port / 32; index2 = port % 32; rtpPort[index1] = rtpPort[index1] & (~(1 << index2)); if (fd >= 0) close(fd); return 0; } int rtp_get_hdl_port() { WORD port = rtpHdlPortSelect; WORD i; for (i = 0; i < RTP_MAX_NUM_OF_PORT; i++) { if (rtpHdlPort[port].flag != 0) { if (++port >= RTP_MAX_NUM_OF_PORT) port = 0; continue; } return port; } return -1; } int rtp_allocate_port(BYTE sapIndex, WORD usrPort, WORD *rtpPort) { int hdlPort, udpPort; if (sapIndex >= RTP_MAX_NUM_OF_SAP) return -1; if ((hdlPort = rtp_get_hdl_port()) < 0) return -1; if ((udpPort = rtp_get_udp_port(hdlPort)) < 0) return -1; rtpHdlPort[hdlPort].flag = 1; rtpHdlPort[hdlPort].sapIndex = sapIndex; rtpHdlPort[hdlPort].usrPort = usrPort; rtpHdlPort[hdlPort].timer = RTP_HANDSHAKE_TIMER; rtpHdlPortSelect = (hdlPort + 1) & RTP_MAX_NUM_OF_PORT_1; *rtpPort = udpPort * 2 + RTP_BASE_UDP_PORT; return hdlPort; } int rtp_release_port(BYTE sapIndex, WORD usrPort, WORD rtpPort, WORD hdlPort) { if (hdlPort >= RTP_MAX_NUM_OF_PORT) return -1; if (rtpHdlPort[hdlPort].sapIndex != sapIndex) return -2; else if (rtpHdlPort[hdlPort].usrPort != usrPort) return -3; else if ((rtpHdlPort[hdlPort].rtpPort * 2 + RTP_BASE_UDP_PORT) != rtpPort) return -4; rtp_release_udp_port(hdlPort); rtp_port_init(hdlPort); return 0; } int rtp_sess_update(BYTE sapIndex, WORD usrPort, WORD hdlPort, RTP_SESSION *sess) { if (hdlPort >= RTP_MAX_NUM_OF_PORT) return -1; if ((rtpHdlPort[hdlPort].sapIndex != sapIndex) || (rtpHdlPort[hdlPort].usrPort != usrPort)) return -1; memcpy((BYTE *) &rtpHdlPort[hdlPort].sess, (BYTE *) sess, sizeof(RTP_SESSION)); rtpHdlPort[hdlPort].inc = rtpHdlPort[hdlPort].sess.interval * 8; return 0; } int rtp_set_mode(BYTE sapIndex, WORD usrPort, WORD hdlPort, BYTE mode) { if ((hdlPort >= RTP_MAX_NUM_OF_PORT) || (mode > RTP_MODE_SENDRECV)) return -1; if ((rtpHdlPort[hdlPort].sapIndex != sapIndex) || (rtpHdlPort[hdlPort].usrPort != usrPort)) return -1; rtpHdlPort[hdlPort].mode = mode; return 0; } int rtp_bind(RTP_SAP *sap) { BYTE i; if ((sap == NULL) || (sap->rtp_handshake == NULL)) return -1; for (i = 0; i < RTP_MAX_NUM_OF_SAP; i++) { if (rtpSap[i].rtp_handshake != NULL) continue; memcpy((BYTE *) &rtpSap[i], sap, sizeof(RTP_SAP)); rtpSap[i].name[RTP_MAX_USER_NAME_LEN - 1] = '\0'; return i; } return -1; } int rtp_unbind(RTP_SAP *sap, BYTE sapIndex) { if ((sap == NULL) || (sapIndex >= RTP_MAX_NUM_OF_SAP)) return -1; if (strcmp(sap->name, rtpSap[sapIndex].name) != 0) return -1; rtp_sap_init(sapIndex); return 0; }