1159b3361Sopenharmony_ci/* 2159b3361Sopenharmony_ci * rtp socket communication functions 3159b3361Sopenharmony_ci * 4159b3361Sopenharmony_ci * initially contributed by Felix von Leitner 5159b3361Sopenharmony_ci * 6159b3361Sopenharmony_ci * Copyright (c) 2000 Mark Taylor 7159b3361Sopenharmony_ci * 2010 Robert Hegemann 8159b3361Sopenharmony_ci * 9159b3361Sopenharmony_ci * This library is free software; you can redistribute it and/or 10159b3361Sopenharmony_ci * modify it under the terms of the GNU Library General Public 11159b3361Sopenharmony_ci * License as published by the Free Software Foundation; either 12159b3361Sopenharmony_ci * version 2 of the License, or (at your option) any later version. 13159b3361Sopenharmony_ci * 14159b3361Sopenharmony_ci * This library is distributed in the hope that it will be useful, 15159b3361Sopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 16159b3361Sopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17159b3361Sopenharmony_ci * Library General Public License for more details. 18159b3361Sopenharmony_ci * 19159b3361Sopenharmony_ci * You should have received a copy of the GNU Library General Public 20159b3361Sopenharmony_ci * License along with this library; if not, write to the 21159b3361Sopenharmony_ci * Free Software Foundation, Inc., 59 Temple Place - Suite 330, 22159b3361Sopenharmony_ci * Boston, MA 02111-1307, USA. 23159b3361Sopenharmony_ci */ 24159b3361Sopenharmony_ci 25159b3361Sopenharmony_ci/* $Id$ */ 26159b3361Sopenharmony_ci 27159b3361Sopenharmony_ci#ifdef HAVE_CONFIG_H 28159b3361Sopenharmony_ci# include <config.h> 29159b3361Sopenharmony_ci#endif 30159b3361Sopenharmony_ci 31159b3361Sopenharmony_ci#ifdef HAVE_STDINT_H 32159b3361Sopenharmony_ci# include <stdint.h> 33159b3361Sopenharmony_ci#endif 34159b3361Sopenharmony_ci 35159b3361Sopenharmony_cistruct rtpbits { 36159b3361Sopenharmony_ci int sequence:16; /* sequence number: random */ 37159b3361Sopenharmony_ci int pt:7; /* payload type: 14 for MPEG audio */ 38159b3361Sopenharmony_ci int m:1; /* marker: 0 */ 39159b3361Sopenharmony_ci int cc:4; /* number of CSRC identifiers: 0 */ 40159b3361Sopenharmony_ci int x:1; /* number of extension headers: 0 */ 41159b3361Sopenharmony_ci int p:1; /* is there padding appended: 0 */ 42159b3361Sopenharmony_ci int v:2; /* version: 2 */ 43159b3361Sopenharmony_ci}; 44159b3361Sopenharmony_ci 45159b3361Sopenharmony_cistruct rtpheader { /* in network byte order */ 46159b3361Sopenharmony_ci struct rtpbits b; 47159b3361Sopenharmony_ci int timestamp; /* start: random */ 48159b3361Sopenharmony_ci int ssrc; /* random */ 49159b3361Sopenharmony_ci int iAudioHeader; /* =0?! */ 50159b3361Sopenharmony_ci}; 51159b3361Sopenharmony_ci 52159b3361Sopenharmony_ci 53159b3361Sopenharmony_ci#if !defined( _WIN32 ) && !defined(__MINGW32__) 54159b3361Sopenharmony_ci 55159b3361Sopenharmony_ci#ifdef STDC_HEADERS 56159b3361Sopenharmony_ci# include <stdio.h> 57159b3361Sopenharmony_ci# include <stdarg.h> 58159b3361Sopenharmony_ci# include <stdlib.h> 59159b3361Sopenharmony_ci# include <string.h> 60159b3361Sopenharmony_ci#else 61159b3361Sopenharmony_ci# ifndef HAVE_MEMCPY 62159b3361Sopenharmony_ci# define memcpy(d, s, n) bcopy ((s), (d), (n)) 63159b3361Sopenharmony_ci# define memmove(d, s, n) bcopy ((s), (d), (n)) 64159b3361Sopenharmony_ci# endif 65159b3361Sopenharmony_ci#endif 66159b3361Sopenharmony_ci 67159b3361Sopenharmony_ci#ifdef HAVE_UNISTD_H 68159b3361Sopenharmony_ci# include <unistd.h> 69159b3361Sopenharmony_ci#endif 70159b3361Sopenharmony_ci 71159b3361Sopenharmony_ci#include <sys/types.h> 72159b3361Sopenharmony_ci#include <sys/socket.h> 73159b3361Sopenharmony_ci#ifdef __int8_t_defined 74159b3361Sopenharmony_ci#undef uint8_t 75159b3361Sopenharmony_ci#undef uint16_t 76159b3361Sopenharmony_ci#undef uint32_t 77159b3361Sopenharmony_ci#undef uint64_t 78159b3361Sopenharmony_ci#endif 79159b3361Sopenharmony_ci#include <netinet/in.h> 80159b3361Sopenharmony_ci#include <arpa/inet.h> 81159b3361Sopenharmony_ci 82159b3361Sopenharmony_ci#ifdef WITH_DMALLOC 83159b3361Sopenharmony_ci#include <dmalloc.h> 84159b3361Sopenharmony_ci#endif 85159b3361Sopenharmony_ci 86159b3361Sopenharmony_ci#include "rtp.h" 87159b3361Sopenharmony_ci#include "console.h" 88159b3361Sopenharmony_ci 89159b3361Sopenharmony_citypedef int SOCKET; 90159b3361Sopenharmony_ci 91159b3361Sopenharmony_cistruct rtpheader RTPheader; 92159b3361Sopenharmony_ciSOCKET rtpsocket; 93159b3361Sopenharmony_ci 94159b3361Sopenharmony_ci 95159b3361Sopenharmony_ci/* create a sender socket. */ 96159b3361Sopenharmony_ciint 97159b3361Sopenharmony_cirtp_socket(char const *address, unsigned int port, unsigned int TTL) 98159b3361Sopenharmony_ci{ 99159b3361Sopenharmony_ci int iRet, iLoop = 1; 100159b3361Sopenharmony_ci struct sockaddr_in sin; 101159b3361Sopenharmony_ci unsigned char cTtl = TTL; 102159b3361Sopenharmony_ci char cLoop = 0; 103159b3361Sopenharmony_ci unsigned int tempaddr; 104159b3361Sopenharmony_ci 105159b3361Sopenharmony_ci int iSocket = socket(AF_INET, SOCK_DGRAM, 0); 106159b3361Sopenharmony_ci if (iSocket < 0) { 107159b3361Sopenharmony_ci error_printf("socket() failed.\n"); 108159b3361Sopenharmony_ci return 1; 109159b3361Sopenharmony_ci } 110159b3361Sopenharmony_ci 111159b3361Sopenharmony_ci memset(&sin, 0, sizeof(sin)); 112159b3361Sopenharmony_ci tempaddr = inet_addr(address); 113159b3361Sopenharmony_ci sin.sin_family = AF_INET; 114159b3361Sopenharmony_ci sin.sin_port = htons(port); 115159b3361Sopenharmony_ci sin.sin_addr.s_addr = tempaddr; 116159b3361Sopenharmony_ci 117159b3361Sopenharmony_ci iRet = setsockopt(iSocket, SOL_SOCKET, SO_REUSEADDR, &iLoop, sizeof(int)); 118159b3361Sopenharmony_ci if (iRet < 0) { 119159b3361Sopenharmony_ci error_printf("setsockopt SO_REUSEADDR failed\n"); 120159b3361Sopenharmony_ci close(iSocket); 121159b3361Sopenharmony_ci return 1; 122159b3361Sopenharmony_ci } 123159b3361Sopenharmony_ci 124159b3361Sopenharmony_ci if ((ntohl(tempaddr) >> 28) == 0xe) { 125159b3361Sopenharmony_ci /* only set multicast parameters for multicast destination IPs */ 126159b3361Sopenharmony_ci iRet = setsockopt(iSocket, IPPROTO_IP, IP_MULTICAST_TTL, &cTtl, sizeof(char)); 127159b3361Sopenharmony_ci if (iRet < 0) { 128159b3361Sopenharmony_ci error_printf("setsockopt IP_MULTICAST_TTL failed. multicast in kernel?\n"); 129159b3361Sopenharmony_ci close(iSocket); 130159b3361Sopenharmony_ci return 1; 131159b3361Sopenharmony_ci } 132159b3361Sopenharmony_ci 133159b3361Sopenharmony_ci cLoop = 1; /* !? */ 134159b3361Sopenharmony_ci iRet = setsockopt(iSocket, IPPROTO_IP, IP_MULTICAST_LOOP, &cLoop, sizeof(char)); 135159b3361Sopenharmony_ci if (iRet < 0) { 136159b3361Sopenharmony_ci error_printf("setsockopt IP_MULTICAST_LOOP failed. multicast in kernel?\n"); 137159b3361Sopenharmony_ci close(iSocket); 138159b3361Sopenharmony_ci return 1; 139159b3361Sopenharmony_ci } 140159b3361Sopenharmony_ci } 141159b3361Sopenharmony_ci iRet = connect(iSocket, (struct sockaddr *) &sin, sizeof(struct sockaddr_in)); 142159b3361Sopenharmony_ci if (iRet < 0) { 143159b3361Sopenharmony_ci error_printf("connect IP_MULTICAST_LOOP failed. multicast in kernel?\n"); 144159b3361Sopenharmony_ci close(iSocket); 145159b3361Sopenharmony_ci return 1; 146159b3361Sopenharmony_ci } 147159b3361Sopenharmony_ci 148159b3361Sopenharmony_ci rtpsocket = iSocket; 149159b3361Sopenharmony_ci 150159b3361Sopenharmony_ci return 0; 151159b3361Sopenharmony_ci} 152159b3361Sopenharmony_ci 153159b3361Sopenharmony_ci 154159b3361Sopenharmony_cistatic void 155159b3361Sopenharmony_cirtp_initialization_extra(void) 156159b3361Sopenharmony_ci{ 157159b3361Sopenharmony_ci} 158159b3361Sopenharmony_ci 159159b3361Sopenharmony_cistatic void 160159b3361Sopenharmony_cirtp_close_extra(void) 161159b3361Sopenharmony_ci{ 162159b3361Sopenharmony_ci} 163159b3361Sopenharmony_ci 164159b3361Sopenharmony_ci#else 165159b3361Sopenharmony_ci 166159b3361Sopenharmony_ci#include <Winsock2.h> 167159b3361Sopenharmony_ci#ifndef IP_MULTICAST_TTL 168159b3361Sopenharmony_ci#define IP_MULTICAST_TTL 3 169159b3361Sopenharmony_ci#endif 170159b3361Sopenharmony_ci#include <stdio.h> 171159b3361Sopenharmony_ci#include <stdarg.h> 172159b3361Sopenharmony_ci 173159b3361Sopenharmony_ci#include "rtp.h" 174159b3361Sopenharmony_ci#include "console.h" 175159b3361Sopenharmony_ci 176159b3361Sopenharmony_ci 177159b3361Sopenharmony_cistruct rtpheader RTPheader; 178159b3361Sopenharmony_ciSOCKET rtpsocket; 179159b3361Sopenharmony_ci 180159b3361Sopenharmony_cistatic char * 181159b3361Sopenharmony_cilast_error_message(int err_code) 182159b3361Sopenharmony_ci{ 183159b3361Sopenharmony_ci char *msg; 184159b3361Sopenharmony_ci void *p_msg_buf; 185159b3361Sopenharmony_ci FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER, 186159b3361Sopenharmony_ci (void *) 0, 187159b3361Sopenharmony_ci (DWORD) err_code, 188159b3361Sopenharmony_ci MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR) & p_msg_buf, 0, NULL); 189159b3361Sopenharmony_ci msg = strdup(p_msg_buf); 190159b3361Sopenharmony_ci LocalFree(p_msg_buf); 191159b3361Sopenharmony_ci return msg; 192159b3361Sopenharmony_ci} 193159b3361Sopenharmony_ci 194159b3361Sopenharmony_cistatic int 195159b3361Sopenharmony_ciprint_socket_error(int error) 196159b3361Sopenharmony_ci{ 197159b3361Sopenharmony_ci char *err_txt = last_error_message(error); 198159b3361Sopenharmony_ci error_printf("error %d\n%s\n", error, err_txt); 199159b3361Sopenharmony_ci free(err_txt); 200159b3361Sopenharmony_ci return error; 201159b3361Sopenharmony_ci} 202159b3361Sopenharmony_ci 203159b3361Sopenharmony_cistatic int 204159b3361Sopenharmony_cion_socket_error(SOCKET s) 205159b3361Sopenharmony_ci{ 206159b3361Sopenharmony_ci int error = WSAGetLastError(); 207159b3361Sopenharmony_ci print_socket_error(error); 208159b3361Sopenharmony_ci if (s != INVALID_SOCKET) { 209159b3361Sopenharmony_ci closesocket(s); 210159b3361Sopenharmony_ci } 211159b3361Sopenharmony_ci return error; 212159b3361Sopenharmony_ci} 213159b3361Sopenharmony_ci 214159b3361Sopenharmony_ci/* create a sender socket. */ 215159b3361Sopenharmony_ciint 216159b3361Sopenharmony_cirtp_socket(char const *address, unsigned int port, unsigned int TTL) 217159b3361Sopenharmony_ci{ 218159b3361Sopenharmony_ci char const True = 1; 219159b3361Sopenharmony_ci char const *c = ""; 220159b3361Sopenharmony_ci int error; 221159b3361Sopenharmony_ci UINT ip; 222159b3361Sopenharmony_ci PHOSTENT host; 223159b3361Sopenharmony_ci SOCKET s; 224159b3361Sopenharmony_ci SOCKADDR_IN source, dest; 225159b3361Sopenharmony_ci 226159b3361Sopenharmony_ci source.sin_family = AF_INET; 227159b3361Sopenharmony_ci source.sin_addr.s_addr = htonl(INADDR_ANY); 228159b3361Sopenharmony_ci source.sin_port = htons(0); 229159b3361Sopenharmony_ci 230159b3361Sopenharmony_ci dest.sin_family = AF_INET; 231159b3361Sopenharmony_ci dest.sin_addr.s_addr = inet_addr(address); 232159b3361Sopenharmony_ci 233159b3361Sopenharmony_ci if (!strcmp(address, "255.255.255.255")) { 234159b3361Sopenharmony_ci } 235159b3361Sopenharmony_ci else if (dest.sin_addr.s_addr == INADDR_NONE) { 236159b3361Sopenharmony_ci host = gethostbyname(address); 237159b3361Sopenharmony_ci 238159b3361Sopenharmony_ci if (host) { 239159b3361Sopenharmony_ci dest.sin_addr = *(PIN_ADDR) host->h_addr; 240159b3361Sopenharmony_ci } 241159b3361Sopenharmony_ci else { 242159b3361Sopenharmony_ci error_printf("Unknown host %s\r\n", address); 243159b3361Sopenharmony_ci return 1; 244159b3361Sopenharmony_ci } 245159b3361Sopenharmony_ci } 246159b3361Sopenharmony_ci 247159b3361Sopenharmony_ci dest.sin_port = htons((u_short) port); 248159b3361Sopenharmony_ci 249159b3361Sopenharmony_ci ip = ntohl(dest.sin_addr.s_addr); 250159b3361Sopenharmony_ci 251159b3361Sopenharmony_ci if (IN_CLASSA(ip)) 252159b3361Sopenharmony_ci c = "class A"; 253159b3361Sopenharmony_ci if (IN_CLASSB(ip)) 254159b3361Sopenharmony_ci c = "class B"; 255159b3361Sopenharmony_ci if (IN_CLASSC(ip)) 256159b3361Sopenharmony_ci c = "class C"; 257159b3361Sopenharmony_ci if (IN_CLASSD(ip)) 258159b3361Sopenharmony_ci c = "class D"; 259159b3361Sopenharmony_ci if (ip == INADDR_LOOPBACK) 260159b3361Sopenharmony_ci c = "loopback"; 261159b3361Sopenharmony_ci if (ip == INADDR_BROADCAST) 262159b3361Sopenharmony_ci c = "broadcast"; 263159b3361Sopenharmony_ci 264159b3361Sopenharmony_ci s = socket(AF_INET, SOCK_DGRAM, PF_UNSPEC); 265159b3361Sopenharmony_ci if (s == INVALID_SOCKET) { 266159b3361Sopenharmony_ci error_printf("socket () "); 267159b3361Sopenharmony_ci return on_socket_error(s); 268159b3361Sopenharmony_ci } 269159b3361Sopenharmony_ci error = setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &True, sizeof(True)); 270159b3361Sopenharmony_ci error = bind(s, (struct sockaddr *) &source, sizeof(source)); 271159b3361Sopenharmony_ci if (error == SOCKET_ERROR) { 272159b3361Sopenharmony_ci error_printf("bind () "); 273159b3361Sopenharmony_ci return on_socket_error(s); 274159b3361Sopenharmony_ci } 275159b3361Sopenharmony_ci if (ip == INADDR_BROADCAST) { 276159b3361Sopenharmony_ci error_printf("broadcast %s:%u %s\r\n", inet_ntoa(dest.sin_addr), ntohs(dest.sin_port), c); 277159b3361Sopenharmony_ci error = setsockopt(s, SOL_SOCKET, SO_BROADCAST, &True, sizeof(True)); 278159b3361Sopenharmony_ci if (error == SOCKET_ERROR) { 279159b3361Sopenharmony_ci error_printf("setsockopt (%u, SOL_SOCKET, SO_BROADCAST, ...) ", s); 280159b3361Sopenharmony_ci return on_socket_error(s); 281159b3361Sopenharmony_ci } 282159b3361Sopenharmony_ci } 283159b3361Sopenharmony_ci if (IN_CLASSD(ip)) { 284159b3361Sopenharmony_ci error_printf("multicast %s:%u %s\r\n", inet_ntoa(dest.sin_addr), ntohs(dest.sin_port), c); 285159b3361Sopenharmony_ci error = setsockopt(s, IPPROTO_IP, IP_MULTICAST_TTL, (const char *) &TTL, sizeof(TTL)); 286159b3361Sopenharmony_ci if (error == SOCKET_ERROR) { 287159b3361Sopenharmony_ci error_printf("setsockopt (%u, IPPROTO_IP, IP_MULTICAST_TTL, ...) ", s); 288159b3361Sopenharmony_ci return on_socket_error(s); 289159b3361Sopenharmony_ci } 290159b3361Sopenharmony_ci } 291159b3361Sopenharmony_ci error = connect(s, (PSOCKADDR) & dest, sizeof(SOCKADDR_IN)); 292159b3361Sopenharmony_ci if (error == SOCKET_ERROR) { 293159b3361Sopenharmony_ci error_printf("connect: "); 294159b3361Sopenharmony_ci return on_socket_error(s); 295159b3361Sopenharmony_ci } 296159b3361Sopenharmony_ci rtpsocket = s; 297159b3361Sopenharmony_ci return 0; 298159b3361Sopenharmony_ci} 299159b3361Sopenharmony_ci 300159b3361Sopenharmony_cistatic void 301159b3361Sopenharmony_cirtp_initialization_extra(void) 302159b3361Sopenharmony_ci{ 303159b3361Sopenharmony_ci WSADATA wsaData; 304159b3361Sopenharmony_ci int rc = WSAStartup(MAKEWORD(2, 2), &wsaData); 305159b3361Sopenharmony_ci if (rc != 0) { 306159b3361Sopenharmony_ci print_socket_error(rc); 307159b3361Sopenharmony_ci } 308159b3361Sopenharmony_ci} 309159b3361Sopenharmony_ci 310159b3361Sopenharmony_cistatic void 311159b3361Sopenharmony_cirtp_close_extra(void) 312159b3361Sopenharmony_ci{ 313159b3361Sopenharmony_ci WSACleanup(); 314159b3361Sopenharmony_ci} 315159b3361Sopenharmony_ci 316159b3361Sopenharmony_ci#endif 317159b3361Sopenharmony_ci 318159b3361Sopenharmony_ci 319159b3361Sopenharmony_cistatic int 320159b3361Sopenharmony_cirtp_send(unsigned char const *data, int len) 321159b3361Sopenharmony_ci{ 322159b3361Sopenharmony_ci SOCKET s = rtpsocket; 323159b3361Sopenharmony_ci struct rtpheader *foo = &RTPheader; 324159b3361Sopenharmony_ci char *buffer = malloc(len + sizeof(struct rtpheader)); 325159b3361Sopenharmony_ci int *cast = (int *) foo; 326159b3361Sopenharmony_ci int *outcast = (int *) buffer; 327159b3361Sopenharmony_ci int count, size; 328159b3361Sopenharmony_ci 329159b3361Sopenharmony_ci outcast[0] = htonl(cast[0]); 330159b3361Sopenharmony_ci outcast[1] = htonl(cast[1]); 331159b3361Sopenharmony_ci outcast[2] = htonl(cast[2]); 332159b3361Sopenharmony_ci outcast[3] = htonl(cast[3]); 333159b3361Sopenharmony_ci memmove(buffer + sizeof(struct rtpheader), data, len); 334159b3361Sopenharmony_ci size = len + sizeof(*foo); 335159b3361Sopenharmony_ci count = send(s, buffer, size, 0); 336159b3361Sopenharmony_ci free(buffer); 337159b3361Sopenharmony_ci 338159b3361Sopenharmony_ci return count != size; 339159b3361Sopenharmony_ci} 340159b3361Sopenharmony_ci 341159b3361Sopenharmony_civoid 342159b3361Sopenharmony_cirtp_output(unsigned char const *mp3buffer, int mp3size) 343159b3361Sopenharmony_ci{ 344159b3361Sopenharmony_ci rtp_send(mp3buffer, mp3size); 345159b3361Sopenharmony_ci RTPheader.timestamp += 5; 346159b3361Sopenharmony_ci RTPheader.b.sequence++; 347159b3361Sopenharmony_ci} 348159b3361Sopenharmony_ci 349159b3361Sopenharmony_civoid 350159b3361Sopenharmony_cirtp_initialization(void) 351159b3361Sopenharmony_ci{ 352159b3361Sopenharmony_ci struct rtpheader *foo = &RTPheader; 353159b3361Sopenharmony_ci foo->b.v = 2; 354159b3361Sopenharmony_ci foo->b.p = 0; 355159b3361Sopenharmony_ci foo->b.x = 0; 356159b3361Sopenharmony_ci foo->b.cc = 0; 357159b3361Sopenharmony_ci foo->b.m = 0; 358159b3361Sopenharmony_ci foo->b.pt = 14; /* MPEG Audio */ 359159b3361Sopenharmony_ci foo->b.sequence = rand() & 65535; 360159b3361Sopenharmony_ci foo->timestamp = rand(); 361159b3361Sopenharmony_ci foo->ssrc = rand(); 362159b3361Sopenharmony_ci foo->iAudioHeader = 0; 363159b3361Sopenharmony_ci rtp_initialization_extra(); 364159b3361Sopenharmony_ci} 365159b3361Sopenharmony_ci 366159b3361Sopenharmony_civoid 367159b3361Sopenharmony_cirtp_deinitialization(void) 368159b3361Sopenharmony_ci{ 369159b3361Sopenharmony_ci rtp_close_extra(); 370159b3361Sopenharmony_ci} 371