#include "asterisk/network.h"
#include "asterisk/frame.h"
#include "asterisk/io.h"
#include "asterisk/sched.h"
#include "asterisk/channel.h"
Go to the source code of this file.
Definition in file udptl.h.
typedef int(*) ast_udptl_callback(struct ast_udptl *udptl, struct ast_frame *f, void *data) |
anonymous enum |
UDPTL_ERROR_CORRECTION_NONE | |
UDPTL_ERROR_CORRECTION_FEC | |
UDPTL_ERROR_CORRECTION_REDUNDANCY |
Definition at line 36 of file udptl.h.
00036 { 00037 UDPTL_ERROR_CORRECTION_NONE, 00038 UDPTL_ERROR_CORRECTION_FEC, 00039 UDPTL_ERROR_CORRECTION_REDUNDANCY 00040 };
int ast_udptl_bridge | ( | struct ast_channel * | c0, | |
struct ast_channel * | c1, | |||
int | flags, | |||
struct ast_frame ** | fo, | |||
struct ast_channel ** | rc | |||
) |
Definition at line 973 of file udptl.c.
References ast_channel_lock, ast_channel_trylock, ast_channel_unlock, ast_check_hangup(), ast_debug, AST_FRAME_MODEM, ast_frfree, ast_inet_ntoa(), ast_log(), ast_read(), ast_udptl_get_peer(), ast_waitfor_n(), ast_write(), f, get_proto(), ast_udptl_protocol::get_udptl_info, inaddrcmp(), LOG_WARNING, ast_channel::masq, ast_channel::masqr, ast_channel::name, ast_udptl_protocol::set_udptl_peer, and ast_channel::tech_pvt.
00974 { 00975 struct ast_frame *f; 00976 struct ast_channel *who; 00977 struct ast_channel *cs[3]; 00978 struct ast_udptl *p0; 00979 struct ast_udptl *p1; 00980 struct ast_udptl_protocol *pr0; 00981 struct ast_udptl_protocol *pr1; 00982 struct sockaddr_in ac0; 00983 struct sockaddr_in ac1; 00984 struct sockaddr_in t0; 00985 struct sockaddr_in t1; 00986 void *pvt0; 00987 void *pvt1; 00988 int to; 00989 00990 ast_channel_lock(c0); 00991 while (ast_channel_trylock(c1)) { 00992 ast_channel_unlock(c0); 00993 usleep(1); 00994 ast_channel_lock(c0); 00995 } 00996 pr0 = get_proto(c0); 00997 pr1 = get_proto(c1); 00998 if (!pr0) { 00999 ast_log(LOG_WARNING, "Can't find native functions for channel '%s'\n", c0->name); 01000 ast_channel_unlock(c0); 01001 ast_channel_unlock(c1); 01002 return -1; 01003 } 01004 if (!pr1) { 01005 ast_log(LOG_WARNING, "Can't find native functions for channel '%s'\n", c1->name); 01006 ast_channel_unlock(c0); 01007 ast_channel_unlock(c1); 01008 return -1; 01009 } 01010 pvt0 = c0->tech_pvt; 01011 pvt1 = c1->tech_pvt; 01012 p0 = pr0->get_udptl_info(c0); 01013 p1 = pr1->get_udptl_info(c1); 01014 if (!p0 || !p1) { 01015 /* Somebody doesn't want to play... */ 01016 ast_channel_unlock(c0); 01017 ast_channel_unlock(c1); 01018 return -2; 01019 } 01020 if (pr0->set_udptl_peer(c0, p1)) { 01021 ast_log(LOG_WARNING, "Channel '%s' failed to talk to '%s'\n", c0->name, c1->name); 01022 memset(&ac1, 0, sizeof(ac1)); 01023 } else { 01024 /* Store UDPTL peer */ 01025 ast_udptl_get_peer(p1, &ac1); 01026 } 01027 if (pr1->set_udptl_peer(c1, p0)) { 01028 ast_log(LOG_WARNING, "Channel '%s' failed to talk back to '%s'\n", c1->name, c0->name); 01029 memset(&ac0, 0, sizeof(ac0)); 01030 } else { 01031 /* Store UDPTL peer */ 01032 ast_udptl_get_peer(p0, &ac0); 01033 } 01034 ast_channel_unlock(c0); 01035 ast_channel_unlock(c1); 01036 cs[0] = c0; 01037 cs[1] = c1; 01038 cs[2] = NULL; 01039 for (;;) { 01040 if ((c0->tech_pvt != pvt0) || 01041 (c1->tech_pvt != pvt1) || 01042 (c0->masq || c0->masqr || c1->masq || c1->masqr)) { 01043 ast_debug(1, "Oooh, something is weird, backing out\n"); 01044 /* Tell it to try again later */ 01045 return -3; 01046 } 01047 to = -1; 01048 ast_udptl_get_peer(p1, &t1); 01049 ast_udptl_get_peer(p0, &t0); 01050 if (inaddrcmp(&t1, &ac1)) { 01051 ast_debug(1, "Oooh, '%s' changed end address to %s:%d\n", 01052 c1->name, ast_inet_ntoa(t1.sin_addr), ntohs(t1.sin_port)); 01053 ast_debug(1, "Oooh, '%s' was %s:%d\n", 01054 c1->name, ast_inet_ntoa(ac1.sin_addr), ntohs(ac1.sin_port)); 01055 memcpy(&ac1, &t1, sizeof(ac1)); 01056 } 01057 if (inaddrcmp(&t0, &ac0)) { 01058 ast_debug(1, "Oooh, '%s' changed end address to %s:%d\n", 01059 c0->name, ast_inet_ntoa(t0.sin_addr), ntohs(t0.sin_port)); 01060 ast_debug(1, "Oooh, '%s' was %s:%d\n", 01061 c0->name, ast_inet_ntoa(ac0.sin_addr), ntohs(ac0.sin_port)); 01062 memcpy(&ac0, &t0, sizeof(ac0)); 01063 } 01064 who = ast_waitfor_n(cs, 2, &to); 01065 if (!who) { 01066 ast_debug(1, "Ooh, empty read...\n"); 01067 /* check for hangup / whentohangup */ 01068 if (ast_check_hangup(c0) || ast_check_hangup(c1)) 01069 break; 01070 continue; 01071 } 01072 f = ast_read(who); 01073 if (!f) { 01074 *fo = f; 01075 *rc = who; 01076 ast_debug(1, "Oooh, got a %s\n", f ? "digit" : "hangup"); 01077 /* That's all we needed */ 01078 return 0; 01079 } else { 01080 if (f->frametype == AST_FRAME_MODEM) { 01081 /* Forward T.38 frames if they happen upon us */ 01082 if (who == c0) { 01083 ast_write(c1, f); 01084 } else if (who == c1) { 01085 ast_write(c0, f); 01086 } 01087 } 01088 ast_frfree(f); 01089 } 01090 /* Swap priority. Not that it's a big deal at this point */ 01091 cs[2] = cs[0]; 01092 cs[0] = cs[1]; 01093 cs[1] = cs[2]; 01094 } 01095 return -1; 01096 }
void ast_udptl_destroy | ( | struct ast_udptl * | udptl | ) |
Definition at line 885 of file udptl.c.
References ast_free, ast_io_remove(), ast_udptl::fd, ast_udptl::io, and ast_udptl::ioid.
Referenced by __sip_destroy(), create_addr_from_peer(), and sip_alloc().
00886 { 00887 if (udptl->ioid) 00888 ast_io_remove(udptl->io, udptl->ioid); 00889 if (udptl->fd > -1) 00890 close(udptl->fd); 00891 ast_free(udptl); 00892 }
int ast_udptl_fd | ( | struct ast_udptl * | udptl | ) |
Definition at line 615 of file udptl.c.
References ast_udptl::fd.
Referenced by __oh323_new(), and sip_new().
00616 { 00617 return udptl->fd; 00618 }
void ast_udptl_get_current_formats | ( | struct ast_udptl * | udptl, | |
int * | astFormats, | |||
int * | nonAstFormats | |||
) |
int ast_udptl_get_error_correction_scheme | ( | struct ast_udptl * | udptl | ) |
Definition at line 706 of file udptl.c.
References ast_log(), ast_udptl::error_correction_scheme, and LOG_WARNING.
Referenced by set_t38_capabilities().
00707 { 00708 if (udptl) 00709 return udptl->error_correction_scheme; 00710 else { 00711 ast_log(LOG_WARNING, "udptl structure is null\n"); 00712 return -1; 00713 } 00714 }
int ast_udptl_get_far_max_datagram | ( | struct ast_udptl * | udptl | ) |
Definition at line 746 of file udptl.c.
References ast_log(), ast_udptl::far_max_datagram_size, and LOG_WARNING.
00747 { 00748 if (udptl) 00749 return udptl->far_max_datagram_size; 00750 else { 00751 ast_log(LOG_WARNING, "udptl structure is null\n"); 00752 return -1; 00753 } 00754 }
int ast_udptl_get_local_max_datagram | ( | struct ast_udptl * | udptl | ) |
Definition at line 736 of file udptl.c.
References ast_log(), ast_udptl::local_max_datagram_size, and LOG_WARNING.
Referenced by add_sdp().
00737 { 00738 if (udptl) 00739 return udptl->local_max_datagram_size; 00740 else { 00741 ast_log(LOG_WARNING, "udptl structure is null\n"); 00742 return -1; 00743 } 00744 }
void ast_udptl_get_peer | ( | struct ast_udptl * | udptl, | |
struct sockaddr_in * | them | |||
) |
Definition at line 866 of file udptl.c.
References ast_udptl::them.
Referenced by ast_udptl_bridge(), and sip_set_udptl_peer().
00867 { 00868 memset(them, 0, sizeof(*them)); 00869 them->sin_family = AF_INET; 00870 them->sin_port = udptl->them.sin_port; 00871 them->sin_addr = udptl->them.sin_addr; 00872 }
void ast_udptl_get_us | ( | struct ast_udptl * | udptl, | |
struct sockaddr_in * | us | |||
) |
void ast_udptl_init | ( | void | ) |
Definition at line 1330 of file udptl.c.
References __ast_udptl_reload(), ast_cli_register_multiple(), and cli_udptl.
Referenced by main().
01331 { 01332 ast_cli_register_multiple(cli_udptl, sizeof(cli_udptl) / sizeof(struct ast_cli_entry)); 01333 __ast_udptl_reload(0); 01334 }
int ast_udptl_lookup_code | ( | struct ast_udptl * | udptl, | |
int | isAstFormat, | |||
int | code | |||
) |
struct ast_udptl* ast_udptl_new | ( | struct sched_context * | sched, | |
struct io_context * | io, | |||
int | callbackmode | |||
) |
Definition at line 848 of file udptl.c.
References ast_udptl_new_with_bindaddr(), io, and sched.
00849 { 00850 struct in_addr ia; 00851 memset(&ia, 0, sizeof(ia)); 00852 return ast_udptl_new_with_bindaddr(sched, io, callbackmode, ia); 00853 }
struct ast_udptl* ast_udptl_new_with_bindaddr | ( | struct sched_context * | sched, | |
struct io_context * | io, | |||
int | callbackmode, | |||
struct in_addr | in | |||
) |
Definition at line 772 of file udptl.c.
References ast_calloc, ast_free, ast_io_add(), AST_IO_IN, ast_log(), ast_random(), errno, ast_udptl::flags, io, LOG_WARNING, sched, UDPTL_ERROR_CORRECTION_FEC, UDPTL_ERROR_CORRECTION_NONE, UDPTL_ERROR_CORRECTION_REDUNDANCY, and udptlread().
Referenced by ast_udptl_new(), create_addr_from_peer(), handle_request_invite(), and sip_alloc().
00773 { 00774 struct ast_udptl *udptl; 00775 int x; 00776 int startplace; 00777 int i; 00778 long int flags; 00779 00780 if (!(udptl = ast_calloc(1, sizeof(*udptl)))) 00781 return NULL; 00782 00783 if (udptlfectype == 2) 00784 udptl->error_correction_scheme = UDPTL_ERROR_CORRECTION_FEC; 00785 else if (udptlfectype == 1) 00786 udptl->error_correction_scheme = UDPTL_ERROR_CORRECTION_REDUNDANCY; 00787 else 00788 udptl->error_correction_scheme = UDPTL_ERROR_CORRECTION_NONE; 00789 udptl->error_correction_span = udptlfecspan; 00790 udptl->error_correction_entries = udptlfecentries; 00791 00792 udptl->far_max_datagram_size = udptlmaxdatagram; 00793 udptl->local_max_datagram_size = udptlmaxdatagram; 00794 00795 memset(&udptl->rx, 0, sizeof(udptl->rx)); 00796 memset(&udptl->tx, 0, sizeof(udptl->tx)); 00797 for (i = 0; i <= UDPTL_BUF_MASK; i++) { 00798 udptl->rx[i].buf_len = -1; 00799 udptl->tx[i].buf_len = -1; 00800 } 00801 00802 udptl->them.sin_family = AF_INET; 00803 udptl->us.sin_family = AF_INET; 00804 00805 if ((udptl->fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { 00806 ast_free(udptl); 00807 ast_log(LOG_WARNING, "Unable to allocate socket: %s\n", strerror(errno)); 00808 return NULL; 00809 } 00810 flags = fcntl(udptl->fd, F_GETFL); 00811 fcntl(udptl->fd, F_SETFL, flags | O_NONBLOCK); 00812 #ifdef SO_NO_CHECK 00813 if (nochecksums) 00814 setsockopt(udptl->fd, SOL_SOCKET, SO_NO_CHECK, &nochecksums, sizeof(nochecksums)); 00815 #endif 00816 /* Find us a place */ 00817 x = (udptlstart == udptlend) ? udptlstart : (ast_random() % (udptlend - udptlstart)) + udptlstart; 00818 startplace = x; 00819 for (;;) { 00820 udptl->us.sin_port = htons(x); 00821 udptl->us.sin_addr = addr; 00822 if (bind(udptl->fd, (struct sockaddr *) &udptl->us, sizeof(udptl->us)) == 0) 00823 break; 00824 if (errno != EADDRINUSE) { 00825 ast_log(LOG_WARNING, "Unexpected bind error: %s\n", strerror(errno)); 00826 close(udptl->fd); 00827 ast_free(udptl); 00828 return NULL; 00829 } 00830 if (++x > udptlend) 00831 x = udptlstart; 00832 if (x == startplace) { 00833 ast_log(LOG_WARNING, "No UDPTL ports remaining\n"); 00834 close(udptl->fd); 00835 ast_free(udptl); 00836 return NULL; 00837 } 00838 } 00839 if (io && sched && callbackmode) { 00840 /* Operate this one in a callback mode */ 00841 udptl->sched = sched; 00842 udptl->io = io; 00843 udptl->ioid = ast_io_add(udptl->io, udptl->fd, udptlread, AST_IO_IN, udptl); 00844 } 00845 return udptl; 00846 }
void ast_udptl_offered_from_local | ( | struct ast_udptl * | udptl, | |
int | local | |||
) |
Definition at line 698 of file udptl.c.
References ast_log(), LOG_WARNING, and ast_udptl::udptl_offered_from_local.
Referenced by transmit_invite(), and transmit_response_with_t38_sdp().
00699 { 00700 if (udptl) 00701 udptl->udptl_offered_from_local = local; 00702 else 00703 ast_log(LOG_WARNING, "udptl structure is null\n"); 00704 }
int ast_udptl_proto_register | ( | struct ast_udptl_protocol * | proto | ) |
Definition at line 942 of file udptl.c.
References ast_log(), AST_RWLIST_INSERT_TAIL, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_udptl_protocol::list, LOG_WARNING, and ast_udptl_protocol::type.
Referenced by load_module().
00943 { 00944 struct ast_udptl_protocol *cur; 00945 00946 AST_RWLIST_WRLOCK(&protos); 00947 AST_RWLIST_TRAVERSE(&protos, cur, list) { 00948 if (cur->type == proto->type) { 00949 ast_log(LOG_WARNING, "Tried to register same protocol '%s' twice\n", cur->type); 00950 AST_RWLIST_UNLOCK(&protos); 00951 return -1; 00952 } 00953 } 00954 AST_RWLIST_INSERT_TAIL(&protos, proto, list); 00955 AST_RWLIST_UNLOCK(&protos); 00956 return 0; 00957 }
void ast_udptl_proto_unregister | ( | struct ast_udptl_protocol * | proto | ) |
Definition at line 935 of file udptl.c.
References AST_RWLIST_REMOVE, AST_RWLIST_UNLOCK, and AST_RWLIST_WRLOCK.
Referenced by unload_module().
00936 { 00937 AST_RWLIST_WRLOCK(&protos); 00938 AST_RWLIST_REMOVE(&protos, proto, list); 00939 AST_RWLIST_UNLOCK(&protos); 00940 }
Definition at line 647 of file udptl.c.
References ast_assert, ast_debug, AST_FRIENDLY_OFFSET, ast_inet_ntoa(), ast_log(), ast_null_frame, ast_verb, errno, ast_udptl::f, ast_udptl::fd, len(), LOG_WARNING, ast_udptl::nat, ast_udptl::rawdata, ast_udptl::them, udptl_debug_test_addr(), and udptl_rx_packet().
Referenced by sip_rtp_read(), skinny_rtp_read(), and udptlread().
00648 { 00649 int res; 00650 struct sockaddr_in sin; 00651 socklen_t len; 00652 uint16_t seqno = 0; 00653 uint16_t *udptlheader; 00654 00655 len = sizeof(sin); 00656 00657 /* Cache where the header will go */ 00658 res = recvfrom(udptl->fd, 00659 udptl->rawdata + AST_FRIENDLY_OFFSET, 00660 sizeof(udptl->rawdata) - AST_FRIENDLY_OFFSET, 00661 0, 00662 (struct sockaddr *) &sin, 00663 &len); 00664 udptlheader = (uint16_t *)(udptl->rawdata + AST_FRIENDLY_OFFSET); 00665 if (res < 0) { 00666 if (errno != EAGAIN) 00667 ast_log(LOG_WARNING, "UDPTL read error: %s\n", strerror(errno)); 00668 ast_assert(errno != EBADF); 00669 return &ast_null_frame; 00670 } 00671 00672 /* Ignore if the other side hasn't been given an address yet. */ 00673 if (!udptl->them.sin_addr.s_addr || !udptl->them.sin_port) 00674 return &ast_null_frame; 00675 00676 if (udptl->nat) { 00677 /* Send to whoever sent to us */ 00678 if ((udptl->them.sin_addr.s_addr != sin.sin_addr.s_addr) || 00679 (udptl->them.sin_port != sin.sin_port)) { 00680 memcpy(&udptl->them, &sin, sizeof(udptl->them)); 00681 ast_debug(1, "UDPTL NAT: Using address %s:%d\n", ast_inet_ntoa(udptl->them.sin_addr), ntohs(udptl->them.sin_port)); 00682 } 00683 } 00684 00685 if (udptl_debug_test_addr(&sin)) { 00686 ast_verb(1, "Got UDPTL packet from %s:%d (type %d, seq %d, len %d)\n", 00687 ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port), 0, seqno, res); 00688 } 00689 #if 0 00690 printf("Got UDPTL packet from %s:%d (seq %d, len = %d)\n", ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port), seqno, res); 00691 #endif 00692 if (udptl_rx_packet(udptl, udptl->rawdata + AST_FRIENDLY_OFFSET, res) < 1) 00693 return &ast_null_frame; 00694 00695 return &udptl->f[0]; 00696 }
void ast_udptl_reload | ( | void | ) |
Definition at line 1325 of file udptl.c.
References __ast_udptl_reload().
01326 { 01327 __ast_udptl_reload(1); 01328 }
void ast_udptl_reset | ( | struct ast_udptl * | udptl | ) |
void ast_udptl_set_callback | ( | struct ast_udptl * | udptl, | |
ast_udptl_callback | callback | |||
) |
Definition at line 625 of file udptl.c.
References ast_udptl::callback.
00626 { 00627 udptl->callback = callback; 00628 }
void ast_udptl_set_data | ( | struct ast_udptl * | udptl, | |
void * | data | |||
) |
Definition at line 620 of file udptl.c.
References ast_udptl::data.
00621 { 00622 udptl->data = data; 00623 }
void ast_udptl_set_error_correction_scheme | ( | struct ast_udptl * | udptl, | |
int | ec | |||
) |
Definition at line 716 of file udptl.c.
References ast_log(), ast_udptl::error_correction_scheme, LOG_WARNING, UDPTL_ERROR_CORRECTION_FEC, UDPTL_ERROR_CORRECTION_NONE, and UDPTL_ERROR_CORRECTION_REDUNDANCY.
Referenced by process_sdp().
00717 { 00718 if (udptl) { 00719 switch (ec) { 00720 case UDPTL_ERROR_CORRECTION_FEC: 00721 udptl->error_correction_scheme = UDPTL_ERROR_CORRECTION_FEC; 00722 break; 00723 case UDPTL_ERROR_CORRECTION_REDUNDANCY: 00724 udptl->error_correction_scheme = UDPTL_ERROR_CORRECTION_REDUNDANCY; 00725 break; 00726 case UDPTL_ERROR_CORRECTION_NONE: 00727 udptl->error_correction_scheme = UDPTL_ERROR_CORRECTION_NONE; 00728 break; 00729 default: 00730 ast_log(LOG_WARNING, "error correction parameter invalid\n"); 00731 }; 00732 } else 00733 ast_log(LOG_WARNING, "udptl structure is null\n"); 00734 }
void ast_udptl_set_far_max_datagram | ( | struct ast_udptl * | udptl, | |
int | max_datagram | |||
) |
Definition at line 764 of file udptl.c.
References ast_log(), ast_udptl::far_max_datagram_size, and LOG_WARNING.
Referenced by process_sdp().
00765 { 00766 if (udptl) 00767 udptl->far_max_datagram_size = max_datagram; 00768 else 00769 ast_log(LOG_WARNING, "udptl structure is null\n"); 00770 }
void ast_udptl_set_local_max_datagram | ( | struct ast_udptl * | udptl, | |
int | max_datagram | |||
) |
Definition at line 756 of file udptl.c.
References ast_log(), ast_udptl::local_max_datagram_size, and LOG_WARNING.
Referenced by process_sdp().
00757 { 00758 if (udptl) 00759 udptl->local_max_datagram_size = max_datagram; 00760 else 00761 ast_log(LOG_WARNING, "udptl structure is null\n"); 00762 }
void ast_udptl_set_m_type | ( | struct ast_udptl * | udptl, | |
int | pt | |||
) |
void ast_udptl_set_peer | ( | struct ast_udptl * | udptl, | |
struct sockaddr_in * | them | |||
) |
Definition at line 860 of file udptl.c.
References ast_udptl::them.
Referenced by process_sdp().
00861 { 00862 udptl->them.sin_port = them->sin_port; 00863 udptl->them.sin_addr = them->sin_addr; 00864 }
void ast_udptl_set_udptlmap_type | ( | struct ast_udptl * | udptl, | |
int | pt, | |||
char * | mimeType, | |||
char * | mimeSubtype | |||
) |
void ast_udptl_setnat | ( | struct ast_udptl * | udptl, | |
int | nat | |||
) |
int ast_udptl_setqos | ( | struct ast_udptl * | udptl, | |
int | tos, | |||
int | cos | |||
) |
Definition at line 855 of file udptl.c.
References ast_netsock_set_qos(), and ast_udptl::fd.
Referenced by sip_alloc().
00856 { 00857 return ast_netsock_set_qos(udptl->fd, tos, cos, "UDPTL"); 00858 }
void ast_udptl_stop | ( | struct ast_udptl * | udptl | ) |
Definition at line 879 of file udptl.c.
References ast_udptl::them.
Referenced by process_sdp(), and stop_media_flows().
00880 { 00881 memset(&udptl->them.sin_addr, 0, sizeof(udptl->them.sin_addr)); 00882 memset(&udptl->them.sin_port, 0, sizeof(udptl->them.sin_port)); 00883 }
Definition at line 894 of file udptl.c.
References AST_FRAME_MODEM, ast_inet_ntoa(), ast_log(), ast_verb, buf, errno, f, len(), LOCAL_FAX_MAX_DATAGRAM, LOG_NOTICE, LOG_WARNING, s, seq, udptl_build_packet(), and udptl_debug_test_addr().
Referenced by sip_write().
00895 { 00896 int seq; 00897 int len; 00898 int res; 00899 uint8_t buf[LOCAL_FAX_MAX_DATAGRAM * 2]; 00900 00901 /* If we have no peer, return immediately */ 00902 if (s->them.sin_addr.s_addr == INADDR_ANY) 00903 return 0; 00904 00905 /* If there is no data length, return immediately */ 00906 if (f->datalen == 0) 00907 return 0; 00908 00909 if (f->frametype != AST_FRAME_MODEM) { 00910 ast_log(LOG_WARNING, "UDPTL can only send T.38 data\n"); 00911 return -1; 00912 } 00913 00914 /* Save seq_no for debug output because udptl_build_packet increments it */ 00915 seq = s->tx_seq_no & 0xFFFF; 00916 00917 /* Cook up the UDPTL packet, with the relevant EC info. */ 00918 len = udptl_build_packet(s, buf, sizeof(buf), f->data, f->datalen); 00919 00920 if (len > 0 && s->them.sin_port && s->them.sin_addr.s_addr) { 00921 if ((res = sendto(s->fd, buf, len, 0, (struct sockaddr *) &s->them, sizeof(s->them))) < 0) 00922 ast_log(LOG_NOTICE, "UDPTL Transmission error to %s:%d: %s\n", ast_inet_ntoa(s->them.sin_addr), ntohs(s->them.sin_port), strerror(errno)); 00923 #if 0 00924 printf("Sent %d bytes of UDPTL data to %s:%d\n", res, ast_inet_ntoa(udptl->them.sin_addr), ntohs(udptl->them.sin_port)); 00925 #endif 00926 if (udptl_debug_test_addr(&s->them)) 00927 ast_verb(1, "Sent UDPTL packet to %s:%d (type %d, seq %d, len %d)\n", 00928 ast_inet_ntoa(s->them.sin_addr), 00929 ntohs(s->them.sin_port), 0, seq, len); 00930 } 00931 00932 return 0; 00933 }