| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366 |
- /*
- * rtp socket communication functions
- *
- * initially contributed by Felix von Leitner
- *
- * Copyright (c) 2000 Mark Taylor
- * 2010 Robert Hegemann
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
- /* $Id$ */
- #ifdef HAVE_CONFIG_H
- # include <config.h>
- #endif
- #ifdef HAVE_STDINT_H
- # include <stdint.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?! */
- };
- #if !defined( _WIN32 ) && !defined(__MINGW32__)
- #ifdef STDC_HEADERS
- # include <stdio.h>
- # include <stdarg.h>
- # include <stdlib.h>
- # include <string.h>
- #else
- # 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>
- #ifdef __int8_t_defined
- #undef uint8_t
- #undef uint16_t
- #undef uint32_t
- #undef uint64_t
- #endif
- #include <netinet/in.h>
- #include <arpa/inet.h>
- #ifdef WITH_DMALLOC
- #include <dmalloc.h>
- #endif
- #include "rtp.h"
- #include "console.h"
- typedef int SOCKET;
- struct rtpheader RTPheader;
- SOCKET rtpsocket;
- /* create a sender socket. */
- int
- rtp_socket(char const *address, unsigned int port, unsigned int TTL)
- {
- 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");
- return 1;
- }
- memset(&sin, 0, sizeof(sin));
- tempaddr = inet_addr(address);
- sin.sin_family = AF_INET;
- sin.sin_port = htons(port);
- sin.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");
- return 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");
- return 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");
- return 1;
- }
- }
- iRet = connect(iSocket, (struct sockaddr *) &sin, sizeof(struct sockaddr_in));
- if (iRet < 0) {
- error_printf("connect IP_MULTICAST_LOOP failed. multicast in kernel?\n");
- return 1;
- }
- rtpsocket = iSocket;
- return 0;
- }
- static void
- rtp_initialization_extra(void)
- {
- }
- static void
- rtp_close_extra(void)
- {
- }
- #else
- #include <Winsock2.h>
- #ifndef IP_MULTICAST_TTL
- #define IP_MULTICAST_TTL 3
- #endif
- #include <stdio.h>
- #include <stdarg.h>
- #include "rtp.h"
- #include "console.h"
- struct rtpheader RTPheader;
- SOCKET rtpsocket;
- static char *
- last_error_message(int err_code)
- {
- char *msg;
- void *p_msg_buf;
- FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER,
- (void *) 0,
- (DWORD) err_code,
- MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR) & p_msg_buf, 0, NULL);
- msg = strdup(p_msg_buf);
- LocalFree(p_msg_buf);
- return msg;
- }
- static int
- print_socket_error(int error)
- {
- char *err_txt = last_error_message(error);
- error_printf("error %d\n%s\n", error, err_txt);
- free(err_txt);
- return error;
- }
- static int
- on_socket_error(SOCKET s)
- {
- int error = WSAGetLastError();
- print_socket_error(error);
- if (s != INVALID_SOCKET) {
- closesocket(s);
- }
- return error;
- }
- /* create a sender socket. */
- int
- rtp_socket(char const *address, unsigned int port, unsigned int TTL)
- {
- char const True = 1;
- char const *c = "";
- int error;
- UINT ip;
- PHOSTENT host;
- SOCKET s;
- SOCKADDR_IN source, dest;
- 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 {
- error_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_printf("socket () ");
- return on_socket_error(s);
- }
- error = setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &True, sizeof(True));
- error = bind(s, (struct sockaddr *) &source, sizeof(source));
- if (error == SOCKET_ERROR) {
- error_printf("bind () ");
- return on_socket_error(s);
- }
- if (ip == INADDR_BROADCAST) {
- error_printf("broadcast %s:%u %s\r\n", inet_ntoa(dest.sin_addr), ntohs(dest.sin_port), c);
- error = setsockopt(s, SOL_SOCKET, SO_BROADCAST, &True, sizeof(True));
- if (error == SOCKET_ERROR) {
- error_printf("setsockopt (%u, SOL_SOCKET, SO_BROADCAST, ...) ", s);
- return on_socket_error(s);
- }
- }
- if (IN_CLASSD(ip)) {
- error_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(TTL));
- if (error == SOCKET_ERROR) {
- error_printf("setsockopt (%u, IPPROTO_IP, IP_MULTICAST_TTL, ...) ", s);
- return on_socket_error(s);
- }
- }
- error = connect(s, (PSOCKADDR) & dest, sizeof(SOCKADDR_IN));
- if (error == SOCKET_ERROR) {
- error_printf("connect: ");
- return on_socket_error(s);
- }
- rtpsocket = s;
- return 0;
- }
- static void
- rtp_initialization_extra(void)
- {
- WSADATA wsaData;
- int rc = WSAStartup(MAKEWORD(2, 2), &wsaData);
- if (rc != 0) {
- print_socket_error(rc);
- }
- }
- static void
- rtp_close_extra(void)
- {
- WSACleanup();
- }
- #endif
- static int
- rtp_send(unsigned char const *data, int len)
- {
- SOCKET s = rtpsocket;
- struct rtpheader *foo = &RTPheader;
- 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);
- size = len + sizeof(*foo);
- count = send(s, buffer, size, 0);
- free(buffer);
- return count != size;
- }
- void
- rtp_output(unsigned char const *mp3buffer, int mp3size)
- {
- rtp_send(mp3buffer, mp3size);
- RTPheader.timestamp += 5;
- RTPheader.b.sequence++;
- }
- void
- rtp_initialization(void)
- {
- struct rtpheader *foo = &RTPheader;
- 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 */
- foo->b.sequence = rand() & 65535;
- foo->timestamp = rand();
- foo->ssrc = rand();
- foo->iAudioHeader = 0;
- rtp_initialization_extra();
- }
- void
- rtp_deinitialization(void)
- {
- rtp_close_extra();
- }
|