/* $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