/* $Id: rtp.c,v 1.12 2003/11/29 11:16:55 aleidinger Exp $ */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#ifndef __GNUC__
# if HAVE_ALLOCA_H
# include <alloca.h>
# else
# ifdef _AIX
#pragma alloca
# else
# ifndef alloca /* predefined by HP cc +Olibcalls */
char *alloca ();
# endif
# endif
# endif
#endif
#include <stdio.h>
#ifdef STDC_HEADERS
# include <stdlib.h>
# include <string.h>
#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 <unistd.h>
#endif
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#ifdef WITH_DMALLOC
#include <dmalloc.h>
#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) {
fprintf (stderr, "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) {
fprintf (stderr, "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) {
fprintf (stderr,
"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) {
fprintf (stderr,
"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 <stdlib.h>
#include <string.h>
#include <netinet/in.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
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)
{
fprintf(stderr,"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)
{
fprintf(stderr,"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) {
fprintf(stderr,"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)
{
fprintf(stderr,"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