/* $Id: rtp.c,v 1.16.8.1 2008/08/05 14:16:06 robert Exp $ */ #ifdef HAVE_CONFIG_H # include #endif #ifdef HAVE_STDINT_H # include #endif #ifndef __GNUC__ # if HAVE_ALLOCA_H # include # else # ifdef _AIX #pragma alloca # else # ifndef alloca /* predefined by HP cc +Olibcalls */ char *alloca(); # endif # endif # endif #endif #include #include #ifdef STDC_HEADERS # include # include #else # ifndef HAVE_STRCHR # define strchr index # define strrchr rindex # endif char *strchr(), *strrchr(); # ifndef HAVE_MEMCPY # define memcpy(d, s, n) bcopy ((s), (d), (n)) # define memmove(d, s, n) bcopy ((s), (d), (n)) # endif #endif #ifdef HAVE_UNISTD_H # include #endif #include #include #include #include #include "console.h" #ifdef WITH_DMALLOC #include #endif struct rtpbits { int sequence:16; /* sequence number: random */ int pt:7; /* payload type: 14 for MPEG audio */ int m:1; /* marker: 0 */ int cc:4; /* number of CSRC identifiers: 0 */ int x:1; /* number of extension headers: 0 */ int p:1; /* is there padding appended: 0 */ int v:2; /* version: 2 */ }; struct rtpheader { /* in network byte order */ struct rtpbits b; int timestamp; /* start: random */ int ssrc; /* random */ int iAudioHeader; /* =0?! */ }; void initrtp(struct rtpheader *foo) { foo->b.v = 2; foo->b.p = 0; foo->b.x = 0; foo->b.cc = 0; foo->b.m = 0; foo->b.pt = 14; /* MPEG Audio */ #ifdef FEFE foo->b.sequence = 42; foo->timestamp = 0; #else foo->b.sequence = rand() & 65535; foo->timestamp = rand(); #endif foo->ssrc = rand(); foo->iAudioHeader = 0; } int sendrtp(int fd, struct sockaddr_in *sSockAddr, struct rtpheader *foo, const void *data, int len) { char *buf = alloca(len + sizeof(struct rtpheader)); int *cast = (int *) foo; int *outcast = (int *) buf; outcast[0] = htonl(cast[0]); outcast[1] = htonl(cast[1]); outcast[2] = htonl(cast[2]); outcast[3] = htonl(cast[3]); memmove(buf + sizeof(struct rtpheader), data, len); return sendto(fd, buf, len + sizeof(*foo), 0, (struct sockaddr *) sSockAddr, sizeof(*sSockAddr)); /* return write(fd,buf,len+sizeof(*foo))==len+sizeof(*foo); */ } /* create a sender socket. */ int makesocket(char *szAddr, unsigned short port, unsigned char TTL, struct sockaddr_in *sSockAddr) { int iRet, iLoop = 1; struct sockaddr_in sin; unsigned char cTtl = TTL; char cLoop = 0; unsigned int tempaddr; int iSocket = socket(AF_INET, SOCK_DGRAM, 0); if (iSocket < 0) { error_printf("socket() failed.\n"); exit(1); } tempaddr = inet_addr(szAddr); sSockAddr->sin_family = sin.sin_family = AF_INET; sSockAddr->sin_port = sin.sin_port = htons(port); sSockAddr->sin_addr.s_addr = tempaddr; iRet = setsockopt(iSocket, SOL_SOCKET, SO_REUSEADDR, &iLoop, sizeof(int)); if (iRet < 0) { error_printf("setsockopt SO_REUSEADDR failed\n"); exit(1); } if ((ntohl(tempaddr) >> 28) == 0xe) { /* only set multicast parameters for multicast destination IPs */ iRet = setsockopt(iSocket, IPPROTO_IP, IP_MULTICAST_TTL, &cTtl, sizeof(char)); if (iRet < 0) { error_printf("setsockopt IP_MULTICAST_TTL failed. multicast in kernel?\n"); exit(1); } cLoop = 1; /* !? */ iRet = setsockopt(iSocket, IPPROTO_IP, IP_MULTICAST_LOOP, &cLoop, sizeof(char)); if (iRet < 0) { error_printf("setsockopt IP_MULTICAST_LOOP failed. multicast in kernel?\n"); exit(1); } } return iSocket; } #if 0 /* */ /* code contributed by Anonymous source. Supposed to be much better */ /* then original code, but only seems to run on windows with MSVC. */ /* and I cannot test it */ /* */ #include #include #include #include #include #include #include #include struct rtpbits { int sequence:16; /* sequence number: random */ int pt:7; /* payload type: 14 for MPEG audio */ int m:1; /* marker: 0 */ int cc:4; /* number of CSRC identifiers: 0 */ int x:1; /* number of extension headers: 0 */ int p:1; /* is there padding appended: 0 */ int v:2; /* version: 2 */ }; struct rtpheader { /* in network byte order */ struct rtpbits b; int timestamp; /* start: random */ int ssrc; /* random */ int iAudioHeader; /* =0?! */ }; void rtp_initialization(struct rtpheader *foo) { foo->b.v = 2; foo->b.p = 0; foo->b.x = 0; foo->b.cc = 0; foo->b.m = 0; foo->b.pt = 14; /* MPEG Audio */ #ifdef FEFE foo->b.sequence = 42; foo->timestamp = 0; #else foo->b.sequence = rand() & 65535; foo->timestamp = rand(); #endif foo->ssrc = rand(); foo->iAudioHeader = 0; } int rtp_send(SOCKET s, struct rtpheader *foo, void *data, int len) { char *buffer = malloc(len + sizeof(struct rtpheader)); int *cast = (int *) foo; int *outcast = (int *) buffer; int count, size; outcast[0] = htonl(cast[0]); outcast[1] = htonl(cast[1]); outcast[2] = htonl(cast[2]); outcast[3] = htonl(cast[3]); memmove(buffer + sizeof(struct rtpheader), data, len); /* return sendto (fd,buf,len+sizeof(*foo),0,(struct sockaddr *)sSockAddr,sizeof(*sSockAddr)); */ /* return write(fd,buf,len+sizeof(*foo))==len+sizeof(*foo); */ size = len + sizeof(*foo); count = send(s, buffer, size, 0); free(buffer); return count != size; } /* create a sender socket. */ int rtp_socket(SOCKET * ps, char *address, unsigned short port, int TTL) { /* int iRet ; */ int iLoop = 1; /* struct sockaddr_in sin ; */ char cTTL = (char) TTL; char cLoop = 0; /* unsigned int tempaddr ; */ BOOL True = TRUE; INT error; char *c = ""; UINT ip; PHOSTENT host; SOCKET s; SOCKADDR_IN source, dest; #if 0 int s = socket(AF_INET, SOCK_DGRAM, 0); if (s < 0) { error_printf("socket() failed.\n"); exit(1); } tempaddr = inet_addr(address); sSockAddr->sin_family = sin.sin_family = AF_INET; sSockAddr->sin_port = sin.sin_port = htons(port); sSockAddr->sin_addr.s_addr = tempaddr; iRet = setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (const char *) &iLoop, sizeof(int)); if (iRet < 0) { error_printf("setsockopt SO_REUSEADDR failed\n"); exit(1); } if ((ntohl(tempaddr) >> 28) == 0xe) { /* only set multicast parameters for multicast destination IPs */ iRet = setsockopt(s, IPPROTO_IP, IP_MULTICAST_TTL, &cTTL, sizeof(char)); if (iRet < 0) { error_printf("setsockopt IP_MULTICAST_TTL failed. multicast in kernel?\n"); exit(1); } cLoop = 1; /* !? */ iRet = setsockopt(s, IPPROTO_IP, IP_MULTICAST_LOOP, &cLoop, sizeof(char)); if (iRet < 0) { error_printf("setsockopt IP_MULTICAST_LOOP failed. multicast in kernel?\n"); exit(1); } } #endif source.sin_family = AF_INET; source.sin_addr.s_addr = htonl(INADDR_ANY); source.sin_port = htons(0); dest.sin_family = AF_INET; dest.sin_addr.s_addr = inet_addr(address); if (!strcmp(address, "255.255.255.255")) { } else if (dest.sin_addr.s_addr == INADDR_NONE) { host = gethostbyname(address); if (host) { dest.sin_addr = *(PIN_ADDR) host->h_addr; } else { printf("Unknown host %s\r\n", address); return 1; } } dest.sin_port = htons((u_short) port); ip = ntohl(dest.sin_addr.s_addr); if (IN_CLASSA(ip)) c = "class A"; if (IN_CLASSB(ip)) c = "class B"; if (IN_CLASSC(ip)) c = "class C"; if (IN_CLASSD(ip)) c = "class D"; if (ip == INADDR_LOOPBACK) c = "loopback"; if (ip == INADDR_BROADCAST) c = "broadcast"; s = socket(AF_INET, SOCK_DGRAM, PF_UNSPEC); if (s == INVALID_SOCKET) { error = WSAGetLastError(); printf("socket () error %d\r\n", error); return error; } error = setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (const char *) &True, sizeof(BOOL)); error = bind(s, (struct sockaddr *) &source, sizeof(source)); if (error == SOCKET_ERROR) { error = WSAGetLastError(); printf("bind () error %d\r\n", error); closesocket(s); return error; } if (ip == INADDR_BROADCAST) { printf("broadcast %s:%u %s\r\n", inet_ntoa(dest.sin_addr), ntohs(dest.sin_port), c); error = setsockopt(s, SOL_SOCKET, SO_BROADCAST, (const char *) &True, sizeof(BOOL)); if (error == SOCKET_ERROR) { error = WSAGetLastError(); printf("setsockopt (%u, SOL_SOCKET, SO_BROADCAST, ...) error %d\r\n", s, error); closesocket(s); return error; } } if (IN_CLASSD(ip)) { printf("multicast %s:%u %s\r\n", inet_ntoa(dest.sin_addr), ntohs(dest.sin_port), c); /* error = setsockopt (s, IPPROTO_IP, IP_MULTICAST_TTL, (const char *) &TTL, sizeof (int)) ; */ error = setsockopt(s, IPPROTO_IP, 3, (const char *) &TTL, sizeof(int)); if (error == SOCKET_ERROR) { error = WSAGetLastError(); printf("setsockopt (%u, IPPROTO_IP, IP_MULTICAST_TTL, ...) error %d\r\n", s, error); closesocket(s); return error; } } error = connect(s, (PSOCKADDR) & dest, sizeof(SOCKADDR_IN)); if (error == SOCKET_ERROR) { printf("connect: error %d\n", WSAGetLastError()); closesocket(s); return error; } *ps = s; return 0; } #endif