Version 0.1.12 from FTP
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@461 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
parent
738689ea86
commit
ede7bca2a7
14
CREDITS
14
CREDITS
|
@ -1,7 +1,3 @@
|
||||||
=== HARDWARE DONORS ===
|
|
||||||
* Thanks to QuickNet Technologies for their donation of an Internet
|
|
||||||
PhoneJack and Linejack card to the project. (http://www.quicknet.net)
|
|
||||||
|
|
||||||
|
|
||||||
=== DEVELOPMENT SUPPORT ===
|
=== DEVELOPMENT SUPPORT ===
|
||||||
I'd like to thank the following companies for helping fund development of
|
I'd like to thank the following companies for helping fund development of
|
||||||
|
@ -9,6 +5,16 @@ Asterisk:
|
||||||
|
|
||||||
Pilosoft, Inc. - for supporting ADSI development in Asterisk
|
Pilosoft, Inc. - for supporting ADSI development in Asterisk
|
||||||
|
|
||||||
|
GFS - for supporting ALSA development
|
||||||
|
|
||||||
|
Telesthetic - for supporting SIP development
|
||||||
|
|
||||||
|
=== HARDWARE DONORS ===
|
||||||
|
* Thanks to QuickNet Technologies for their donation of an Internet
|
||||||
|
PhoneJack and Linejack card to the project. (http://www.quicknet.net)
|
||||||
|
|
||||||
|
=== MISCELLANEOUS PATCHES ===
|
||||||
|
Oliver Daudey - ISDN4Linux fixes
|
||||||
|
|
||||||
=== OTHER SOURCE CODE IN ASTERISK ===
|
=== OTHER SOURCE CODE IN ASTERISK ===
|
||||||
|
|
||||||
|
|
|
@ -11,10 +11,15 @@
|
||||||
# the GNU General Public License
|
# the GNU General Public License
|
||||||
#
|
#
|
||||||
|
|
||||||
CHANNEL_LIBS=chan_vofr.so chan_modem.so \
|
CHANNEL_LIBS=chan_modem.so chan_iax.so chan_sip.so \
|
||||||
chan_modem_aopen.so chan_iax.so chan_oss.so \
|
chan_modem_aopen.so chan_oss.so \
|
||||||
chan_modem_bestdata.so chan_modem_i4l.so
|
chan_modem_bestdata.so chan_modem_i4l.so
|
||||||
|
|
||||||
|
#
|
||||||
|
# If you really want VoFR you can have it :-P
|
||||||
|
#
|
||||||
|
#CHANNEL_LIBS+=chan_vofr
|
||||||
|
|
||||||
CHANNEL_LIBS+=$(shell [ -f /usr/include/linux/ixjuser.h ] && echo chan_phone.so)
|
CHANNEL_LIBS+=$(shell [ -f /usr/include/linux/ixjuser.h ] && echo chan_phone.so)
|
||||||
|
|
||||||
CFLAGS+=-Wno-missing-prototypes -Wno-missing-declarations
|
CFLAGS+=-Wno-missing-prototypes -Wno-missing-declarations
|
||||||
|
|
|
@ -0,0 +1,36 @@
|
||||||
|
;
|
||||||
|
; SIP Configuration for Asterisk
|
||||||
|
;
|
||||||
|
[general]
|
||||||
|
port = 5060 ; Port to bind to
|
||||||
|
bindaddr = 0.0.0.0 ; Address to bind to
|
||||||
|
context = default ; Default for incoming calls
|
||||||
|
|
||||||
|
;[snomsip]
|
||||||
|
;type=friend
|
||||||
|
;secret=blah
|
||||||
|
;host=dynamic
|
||||||
|
;defaultip=192.168.0.59
|
||||||
|
|
||||||
|
;[pingtel]
|
||||||
|
;type=friend
|
||||||
|
;insecure=yes ; Pingtel sends from different portno
|
||||||
|
;username=pingtel
|
||||||
|
;secret=blah
|
||||||
|
;host=dynamic
|
||||||
|
;defaultip=192.168.0.60
|
||||||
|
|
||||||
|
;[cisco]
|
||||||
|
;type=friend
|
||||||
|
;username=cisco
|
||||||
|
;secret=blah
|
||||||
|
;host=dynamic
|
||||||
|
;defaultip=192.168.0.4
|
||||||
|
|
||||||
|
;[cisco1]
|
||||||
|
;type=friend
|
||||||
|
;insecure=yes
|
||||||
|
;username=cisco1
|
||||||
|
;secret=blah
|
||||||
|
;host=dynamic
|
||||||
|
;defaultip=192.168.0.4
|
|
@ -0,0 +1,54 @@
|
||||||
|
/*
|
||||||
|
* Asterisk -- A telephony toolkit for Linux.
|
||||||
|
*
|
||||||
|
* Real-time Transport Protocol support
|
||||||
|
*
|
||||||
|
* Copyright (C) 1999, Mark Spencer
|
||||||
|
*
|
||||||
|
* Mark Spencer <markster@linux-support.net>
|
||||||
|
*
|
||||||
|
* This program is free software, distributed under the terms of
|
||||||
|
* the GNU General Public License
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _ASTERISK_RTP_H
|
||||||
|
#define _ASTERISK_RTP_H
|
||||||
|
|
||||||
|
#include <asterisk/frame.h>
|
||||||
|
#include <asterisk/io.h>
|
||||||
|
#include <asterisk/sched.h>
|
||||||
|
|
||||||
|
#include <netinet/in.h>
|
||||||
|
|
||||||
|
#if defined(__cplusplus) || defined(c_plusplus)
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct ast_rtp;
|
||||||
|
|
||||||
|
typedef int (*ast_rtp_callback)(struct ast_rtp *rtp, struct ast_frame *f, void *data);
|
||||||
|
|
||||||
|
struct ast_rtp *ast_rtp_new(struct sched_context *sched, struct io_context *io);
|
||||||
|
|
||||||
|
void ast_rtp_set_peer(struct ast_rtp *rtp, struct sockaddr_in *them);
|
||||||
|
|
||||||
|
void ast_rtp_get_us(struct ast_rtp *rtp, struct sockaddr_in *us);
|
||||||
|
|
||||||
|
void ast_rtp_destroy(struct ast_rtp *rtp);
|
||||||
|
|
||||||
|
void ast_rtp_set_callback(struct ast_rtp *rtp, ast_rtp_callback callback);
|
||||||
|
|
||||||
|
void ast_rtp_set_data(struct ast_rtp *rtp, void *data);
|
||||||
|
|
||||||
|
int ast_rtp_write(struct ast_rtp *rtp, struct ast_frame *f);
|
||||||
|
|
||||||
|
int ast2rtp(int id);
|
||||||
|
|
||||||
|
int rtp2ast(int id);
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(__cplusplus) || defined(c_plusplus)
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,364 @@
|
||||||
|
/*
|
||||||
|
* Asterisk -- A telephony toolkit for Linux.
|
||||||
|
*
|
||||||
|
* Real-time Protocol Support
|
||||||
|
*
|
||||||
|
* Copyright (C) 1999, Mark Spencer
|
||||||
|
*
|
||||||
|
* Mark Spencer <markster@linux-support.net>
|
||||||
|
*
|
||||||
|
* This program is free software, distributed under the terms of
|
||||||
|
* the GNU General Public License
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
|
||||||
|
#include <asterisk/rtp.h>
|
||||||
|
#include <asterisk/logger.h>
|
||||||
|
#include <asterisk/options.h>
|
||||||
|
#include <asterisk/channel.h>
|
||||||
|
|
||||||
|
static int dtmftimeout = 300; /* 300 samples */
|
||||||
|
|
||||||
|
struct ast_rtp {
|
||||||
|
int s;
|
||||||
|
char resp;
|
||||||
|
struct ast_frame f;
|
||||||
|
unsigned char rawdata[1024 + AST_FRIENDLY_OFFSET];
|
||||||
|
unsigned int ssrc;
|
||||||
|
unsigned int lastts;
|
||||||
|
unsigned int lastrxts;
|
||||||
|
int dtmfcount;
|
||||||
|
struct sockaddr_in us;
|
||||||
|
struct sockaddr_in them;
|
||||||
|
struct timeval rxcore;
|
||||||
|
struct timeval txcore;
|
||||||
|
int *ioid;
|
||||||
|
unsigned short seqno;
|
||||||
|
struct sched_context *sched;
|
||||||
|
struct io_context *io;
|
||||||
|
void *data;
|
||||||
|
ast_rtp_callback callback;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
void ast_rtp_set_data(struct ast_rtp *rtp, void *data)
|
||||||
|
{
|
||||||
|
rtp->data = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ast_rtp_set_callback(struct ast_rtp *rtp, ast_rtp_callback callback)
|
||||||
|
{
|
||||||
|
rtp->callback = callback;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void send_dtmf(struct ast_rtp *rtp)
|
||||||
|
{
|
||||||
|
printf("Sending dtmf: %d (%c)\n", rtp->resp, rtp->resp);
|
||||||
|
rtp->f.frametype = AST_FRAME_DTMF;
|
||||||
|
rtp->f.subclass = rtp->resp;
|
||||||
|
rtp->f.datalen = 0;
|
||||||
|
rtp->f.timelen = 0;
|
||||||
|
rtp->f.mallocd = 0;
|
||||||
|
rtp->f.src = "RTP";
|
||||||
|
rtp->resp = 0;
|
||||||
|
if (rtp->callback)
|
||||||
|
rtp->callback(rtp, &rtp->f, rtp->data);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static void process_rfc2833(struct ast_rtp *rtp, unsigned char *data, int len)
|
||||||
|
{
|
||||||
|
unsigned int event;
|
||||||
|
char resp = 0;
|
||||||
|
event = ntohl(*((unsigned int *)(data)));
|
||||||
|
event >>= 24;
|
||||||
|
#if 0
|
||||||
|
printf("Event: %08x (len = %d)\n", event, len);
|
||||||
|
#endif
|
||||||
|
if (event < 10) {
|
||||||
|
resp = '0' + event;
|
||||||
|
} else if (event < 11) {
|
||||||
|
resp = '*';
|
||||||
|
} else if (event < 12) {
|
||||||
|
resp = '#';
|
||||||
|
} else if (event < 16) {
|
||||||
|
resp = 'A' + (event - 12);
|
||||||
|
}
|
||||||
|
if (rtp->resp && (rtp->resp != resp)) {
|
||||||
|
send_dtmf(rtp);
|
||||||
|
}
|
||||||
|
rtp->resp = resp;
|
||||||
|
rtp->dtmfcount = dtmftimeout;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int rtpread(int *id, int fd, short events, void *cbdata)
|
||||||
|
{
|
||||||
|
struct ast_rtp *rtp = cbdata;
|
||||||
|
int res;
|
||||||
|
struct sockaddr_in sin;
|
||||||
|
int len;
|
||||||
|
unsigned int seqno;
|
||||||
|
int payloadtype;
|
||||||
|
int hdrlen = 12;
|
||||||
|
unsigned int timestamp;
|
||||||
|
|
||||||
|
unsigned int *rtpheader;
|
||||||
|
|
||||||
|
len = sizeof(sin);
|
||||||
|
|
||||||
|
res = recvfrom(rtp->s, rtp->rawdata + AST_FRIENDLY_OFFSET, sizeof(rtp->rawdata) - AST_FRIENDLY_OFFSET,
|
||||||
|
0, (struct sockaddr *)&sin, &len);
|
||||||
|
|
||||||
|
rtpheader = (unsigned int *)(rtp->rawdata + AST_FRIENDLY_OFFSET);
|
||||||
|
if (res < 0) {
|
||||||
|
ast_log(LOG_WARNING, "RTP Read error: %s\n", strerror(errno));
|
||||||
|
if (errno == EBADF)
|
||||||
|
CRASH;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (res < hdrlen) {
|
||||||
|
ast_log(LOG_WARNING, "RTP Read too short\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
/* Get fields */
|
||||||
|
seqno = ntohl(rtpheader[0]);
|
||||||
|
payloadtype = (seqno & 0x7f0000) >> 16;
|
||||||
|
seqno &= 0xffff;
|
||||||
|
timestamp = ntohl(rtpheader[1]);
|
||||||
|
#if 0
|
||||||
|
printf("Got RTP packet from %s:%d (type %d, seq %d, ts %d, len = %d)\n", inet_ntoa(sin.sin_addr), ntohs(sin.sin_port), payloadtype, seqno, timestamp,res - hdrlen);
|
||||||
|
#endif
|
||||||
|
rtp->f.frametype = AST_FRAME_VOICE;
|
||||||
|
rtp->f.subclass = rtp2ast(payloadtype);
|
||||||
|
if (rtp->f.subclass < 0) {
|
||||||
|
if (payloadtype == 101) {
|
||||||
|
/* It's special -- rfc2833 process it */
|
||||||
|
process_rfc2833(rtp, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen);
|
||||||
|
} else
|
||||||
|
ast_log(LOG_NOTICE, "Unknown RTP codec %d received\n", payloadtype);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!rtp->lastrxts)
|
||||||
|
rtp->lastrxts = timestamp;
|
||||||
|
|
||||||
|
if (rtp->dtmfcount) {
|
||||||
|
#if 0
|
||||||
|
printf("dtmfcount was %d\n", rtp->dtmfcount);
|
||||||
|
#endif
|
||||||
|
rtp->dtmfcount -= (timestamp - rtp->lastrxts);
|
||||||
|
if (rtp->dtmfcount < 0)
|
||||||
|
rtp->dtmfcount = 0;
|
||||||
|
#if 0
|
||||||
|
if (dtmftimeout != rtp->dtmfcount)
|
||||||
|
printf("dtmfcount is %d\n", rtp->dtmfcount);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
rtp->lastrxts = timestamp;
|
||||||
|
|
||||||
|
/* Send any pending DTMF */
|
||||||
|
if (rtp->resp && !rtp->dtmfcount) {
|
||||||
|
send_dtmf(rtp);
|
||||||
|
/* Setup the voice frame again */
|
||||||
|
rtp->f.frametype = AST_FRAME_VOICE;
|
||||||
|
rtp->f.subclass = rtp2ast(payloadtype);
|
||||||
|
}
|
||||||
|
rtp->f.mallocd = 0;
|
||||||
|
rtp->f.datalen = res - hdrlen;
|
||||||
|
rtp->f.data = rtp->rawdata + hdrlen + AST_FRIENDLY_OFFSET;
|
||||||
|
rtp->f.offset = hdrlen + AST_FRIENDLY_OFFSET;
|
||||||
|
switch(rtp->f.subclass) {
|
||||||
|
case AST_FORMAT_ULAW:
|
||||||
|
case AST_FORMAT_ALAW:
|
||||||
|
rtp->f.timelen = rtp->f.datalen / 8;
|
||||||
|
break;
|
||||||
|
case AST_FORMAT_SLINEAR:
|
||||||
|
rtp->f.timelen = rtp->f.datalen / 16;
|
||||||
|
break;
|
||||||
|
case AST_FORMAT_GSM:
|
||||||
|
rtp->f.timelen = 20 * (rtp->f.datalen / 33);
|
||||||
|
break;
|
||||||
|
case AST_FORMAT_ADPCM:
|
||||||
|
rtp->f.timelen = rtp->f.datalen / 8;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ast_log(LOG_NOTICE, "Unable to calculate timelen for format %d\n", rtp->f.subclass);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
rtp->f.src = "RTP";
|
||||||
|
if (rtp->callback)
|
||||||
|
rtp->callback(rtp, &rtp->f, rtp->data);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct {
|
||||||
|
int rtp;
|
||||||
|
int ast;
|
||||||
|
} cmap[] = {
|
||||||
|
{ 0, AST_FORMAT_ULAW },
|
||||||
|
{ 3, AST_FORMAT_GSM },
|
||||||
|
{ 4, AST_FORMAT_G723_1 },
|
||||||
|
{ 5, AST_FORMAT_ADPCM },
|
||||||
|
{ 8, AST_FORMAT_ALAW },
|
||||||
|
{ 18, AST_FORMAT_G729A },
|
||||||
|
};
|
||||||
|
|
||||||
|
int rtp2ast(int id)
|
||||||
|
{
|
||||||
|
int x;
|
||||||
|
for (x=0;x<sizeof(cmap) / sizeof(cmap[0]); x++) {
|
||||||
|
if (cmap[x].rtp == id)
|
||||||
|
return cmap[x].ast;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ast2rtp(int id)
|
||||||
|
{
|
||||||
|
int x;
|
||||||
|
for (x=0;x<sizeof(cmap) / sizeof(cmap[0]); x++) {
|
||||||
|
if (cmap[x].ast == id)
|
||||||
|
return cmap[x].rtp;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ast_rtp *ast_rtp_new(struct sched_context *sched, struct io_context *io)
|
||||||
|
{
|
||||||
|
struct ast_rtp *rtp;
|
||||||
|
int x;
|
||||||
|
int flags;
|
||||||
|
rtp = malloc(sizeof(struct ast_rtp));
|
||||||
|
if (!rtp)
|
||||||
|
return NULL;
|
||||||
|
memset(rtp, 0, sizeof(struct ast_rtp));
|
||||||
|
rtp->them.sin_family = AF_INET;
|
||||||
|
rtp->us.sin_family = AF_INET;
|
||||||
|
rtp->s = socket(AF_INET, SOCK_DGRAM, 0);
|
||||||
|
rtp->ssrc = rand();
|
||||||
|
rtp->seqno = rand() & 0xffff;
|
||||||
|
if (rtp->s < 0) {
|
||||||
|
free(rtp);
|
||||||
|
ast_log(LOG_WARNING, "Unable to allocate socket: %s\n", strerror(errno));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
flags = fcntl(rtp->s, F_GETFL);
|
||||||
|
fcntl(rtp->s, F_SETFL, flags | O_NONBLOCK);
|
||||||
|
for (;;) {
|
||||||
|
/* Find us a place */
|
||||||
|
x = (rand() % (65000-1025)) + 1025;
|
||||||
|
/* Must be an even port number by RTP spec */
|
||||||
|
x = x & ~1;
|
||||||
|
rtp->us.sin_port = htons(x);
|
||||||
|
if (!bind(rtp->s, &rtp->us, sizeof(rtp->us)))
|
||||||
|
break;
|
||||||
|
if (errno != EADDRINUSE) {
|
||||||
|
ast_log(LOG_WARNING, "Unexpected bind error: %s\n", strerror(errno));
|
||||||
|
close(rtp->s);
|
||||||
|
free(rtp);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
rtp->io = io;
|
||||||
|
rtp->sched = sched;
|
||||||
|
rtp->ioid = ast_io_add(rtp->io, rtp->s, rtpread, AST_IO_IN, rtp);
|
||||||
|
return rtp;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ast_rtp_set_peer(struct ast_rtp *rtp, struct sockaddr_in *them)
|
||||||
|
{
|
||||||
|
rtp->them.sin_port = them->sin_port;
|
||||||
|
rtp->them.sin_addr = them->sin_addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ast_rtp_get_us(struct ast_rtp *rtp, struct sockaddr_in *us)
|
||||||
|
{
|
||||||
|
memcpy(us, &rtp->us, sizeof(rtp->us));
|
||||||
|
}
|
||||||
|
|
||||||
|
void ast_rtp_destroy(struct ast_rtp *rtp)
|
||||||
|
{
|
||||||
|
if (rtp->ioid)
|
||||||
|
ast_io_remove(rtp->io, rtp->ioid);
|
||||||
|
if (rtp->s > -1)
|
||||||
|
close(rtp->s);
|
||||||
|
free(rtp);
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned int calc_txstamp(struct ast_rtp *rtp)
|
||||||
|
{
|
||||||
|
struct timeval now;
|
||||||
|
unsigned int ms;
|
||||||
|
if (!rtp->txcore.tv_sec && !rtp->txcore.tv_usec) {
|
||||||
|
gettimeofday(&rtp->txcore, NULL);
|
||||||
|
}
|
||||||
|
gettimeofday(&now, NULL);
|
||||||
|
ms = (now.tv_sec - rtp->txcore.tv_sec) * 1000;
|
||||||
|
ms += (now.tv_usec - rtp->txcore.tv_usec);
|
||||||
|
return ms;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ast_rtp_write(struct ast_rtp *rtp, struct ast_frame *_f)
|
||||||
|
{
|
||||||
|
int hdrlen = 12;
|
||||||
|
struct ast_frame *f;
|
||||||
|
int codec;
|
||||||
|
int res;
|
||||||
|
unsigned int ms;
|
||||||
|
unsigned int *rtpheader;
|
||||||
|
|
||||||
|
/* Make sure we have enough space for RTP header */
|
||||||
|
|
||||||
|
if (_f->frametype != AST_FRAME_VOICE) {
|
||||||
|
ast_log(LOG_WARNING, "RTP can only send voice\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
codec = ast2rtp(_f->subclass);
|
||||||
|
if (codec < 0) {
|
||||||
|
ast_log(LOG_WARNING, "Don't know how to send format %d packets with RTP\n", _f->subclass);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_f->offset < hdrlen) {
|
||||||
|
f = ast_frdup(_f);
|
||||||
|
} else
|
||||||
|
f = _f;
|
||||||
|
|
||||||
|
ms = calc_txstamp(rtp) * 8;
|
||||||
|
switch(f->subclass) {
|
||||||
|
case AST_FORMAT_ULAW:
|
||||||
|
case AST_FORMAT_ALAW:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ast_log(LOG_WARNING, "Not sure about timestamp format for codec format %d\n", f->subclass);
|
||||||
|
}
|
||||||
|
rtp->lastts += f->datalen;
|
||||||
|
/* Get a pointer to the header */
|
||||||
|
rtpheader = (unsigned int *)(f->data - hdrlen);
|
||||||
|
rtpheader[0] = htonl((2 << 30) | (codec << 16) | (rtp->seqno++));
|
||||||
|
rtpheader[1] = htonl(rtp->lastts);
|
||||||
|
rtpheader[2] = htonl(rtp->ssrc);
|
||||||
|
if (rtp->them.sin_port && rtp->them.sin_addr.s_addr) {
|
||||||
|
res = sendto(rtp->s, (void *)rtpheader, f->datalen + hdrlen, 0, &rtp->them, sizeof(rtp->them));
|
||||||
|
if (res <0)
|
||||||
|
ast_log(LOG_NOTICE, "RTP Transmission error to %s:%d: %s\n", inet_ntoa(rtp->them.sin_addr), ntohs(rtp->them.sin_port), strerror(errno));
|
||||||
|
#if 0
|
||||||
|
printf("Sent %d bytes of RTP data to %s:%d\n", res, inet_ntoa(rtp->them.sin_addr), ntohs(rtp->them.sin_port));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
Loading…
Reference in New Issue