/*
eXosip - This is the eXtended osip library.
Copyright (C) 2002,2003,2004,2005 Aymeric MOIZARD - jack@atosc.org
eXosip is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
eXosip 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifdef ENABLE_MPATROL
#include <mpatrol.h>
#endif
#include "eXosip2.h"
extern eXosip_t eXosip;
char *
_eXosip_transport_protocol (osip_message_t * msg)
{
osip_via_t *via;
via = (osip_via_t *) osip_list_get (&msg->vias, 0);
if (via == NULL || via->protocol == NULL)
return NULL;
return via->protocol;
}
int
_eXosip_find_protocol (osip_message_t * msg)
{
osip_via_t *via;
via = (osip_via_t *) osip_list_get (&msg->vias, 0);
if (via == NULL || via->protocol == NULL)
return -1;
else if (0 == osip_strcasecmp (via->protocol, "UDP"))
return IPPROTO_UDP;
else if (0 == osip_strcasecmp (via->protocol, "TCP"))
return IPPROTO_TCP;
return -1;;
}
int
_eXosip_tcp_find_socket (char *host, int port)
{
int pos;
struct eXosip_net *net;
net = &eXosip.net_interfaces[1];
for (pos = 0; pos < EXOSIP_MAX_SOCKETS; pos++)
{
if (net->net_socket_tab[pos].socket != 0)
{
if (0 == osip_strcasecmp (net->net_socket_tab[pos].remote_ip, host)
&& port == net->net_socket_tab[pos].remote_port)
return net->net_socket_tab[pos].socket;
}
}
return -1;
}
int
_eXosip_tcp_connect_socket (char *host, int port)
{
int pos;
struct eXosip_net *net;
int res;
struct addrinfo *addrinfo = NULL;
struct addrinfo *curinfo;
int sock = -1;
net = &eXosip.net_interfaces[1];
for (pos = 0; pos < EXOSIP_MAX_SOCKETS; pos++)
{
if (net->net_socket_tab[pos].socket == 0)
{
break;
}
}
if (pos == EXOSIP_MAX_SOCKETS)
return -1;
res = eXosip_get_addrinfo (&addrinfo, host, port, IPPROTO_TCP);
if (res)
return -1;
for (curinfo = addrinfo; curinfo; curinfo = curinfo->ai_next)
{
if (curinfo->ai_protocol && curinfo->ai_protocol != IPPROTO_TCP)
{
OSIP_TRACE (osip_trace
(__FILE__, __LINE__, OSIP_INFO2, NULL,
"eXosip: Skipping protocol %d\n", curinfo->ai_protocol));
continue;
}
sock = (int) socket (curinfo->ai_family, curinfo->ai_socktype,
curinfo->ai_protocol);
if (sock < 0)
{
#if !defined(_WIN32_WCE)
OSIP_TRACE (osip_trace
(__FILE__, __LINE__, OSIP_INFO2, NULL,
"eXosip: Cannot create socket!\n", strerror (errno)));
#endif
continue;
}
if (curinfo->ai_family == AF_INET6)
{
#ifdef IPV6_V6ONLY
if (setsockopt_ipv6only (sock))
{
close (sock);
sock = -1;
OSIP_TRACE (osip_trace
(__FILE__, __LINE__, OSIP_INFO2, NULL,
"eXosip: Cannot set socket option!\n",
strerror (errno)));
continue;
}
#endif /* IPV6_V6ONLY */
}
#if 0
res = bind (sock, (struct sockaddr *) &net->ai_addr, curinfo->ai_addrlen);
if (res < 0)
{
OSIP_TRACE (osip_trace
(__FILE__, __LINE__, OSIP_INFO2, NULL,
"eXosip: Cannot bind socket %s\n", strerror (errno)));
close (sock);
sock = -1;
continue;
}
#endif
res = connect (sock, curinfo->ai_addr, curinfo->ai_addrlen);
if (res < 0)
{
#if !defined(_WIN32_WCE)
OSIP_TRACE (osip_trace
(__FILE__, __LINE__, OSIP_INFO2, NULL,
"eXosip: Cannot bind socket node:%s family:%d %s\n",
host, curinfo->ai_family, strerror (errno)));
#endif
close (sock);
sock = -1;
continue;
}
break;
}
freeaddrinfo (addrinfo);
if (sock > 0)
{
net->net_socket_tab[pos].socket = sock;
osip_strncpy (net->net_socket_tab[pos].remote_ip, host,
sizeof (net->net_socket_tab[pos].remote_ip) - 1);
net->net_socket_tab[pos].remote_port = port;
return sock;
}
return -1;
}
int
eXosip_transport_set (osip_message_t * msg, const char *transport)
{
osip_via_t *via;
via = (osip_via_t *) osip_list_get (&msg->vias, 0);
if (via == NULL || via->protocol == NULL)
return -1;
if (0 == osip_strcasecmp (via->protocol, transport))
return 0;
osip_free (via->protocol);
via->protocol = osip_strdup (transport);
return 0;
}
int
_eXosip_recvfrom (int s, char *buf, int len, unsigned int flags,
struct sockaddr *from, socklen_t * fromlen)
{
int message_size = 0;
int length_done = 0;
int real_size = 0;
int i;
int extra_data_discarded;
if (!eXosip.http_port)
{
return recvfrom (s, buf, len, flags, from, fromlen);
}
/* we get the size of the HTTP data */
i = recv (eXosip.net_interfaces[0].net_socket, (char *) &(message_size), 4, 0);
real_size = message_size;
if (message_size < 0)
{
return -1; /* Connection error? */
}
if (message_size == 0)
{
buf[0] = '\0';
return 0;
}
if (message_size > len - 1)
message_size = len - 1;
length_done = 0;
i = recv (eXosip.net_interfaces[0].net_socket, buf, message_size, 0);
length_done = i;
if (length_done == real_size)
{
return length_done;
}
if (length_done < message_size)
{
/* continue reading up to message_size */
while (length_done < message_size)
{
i =
recv (eXosip.net_interfaces[0].net_socket, buf + length_done,
message_size - length_done, 0);
length_done = length_done + i;
}
}
extra_data_discarded = length_done;
while (extra_data_discarded < real_size)
{
char buf2[2048];
/* We have to discard the end of data... up to the next message */
i = recv (eXosip.net_interfaces[0].net_socket, buf2, 2048, 0);
extra_data_discarded = extra_data_discarded + i;
}
return length_done;
}
int
_eXosip_sendto (int s, const void *buf, size_t len, int flags,
const struct sockaddr *to, socklen_t tolen)
{
int i;
char buf2[10000];
if (!eXosip.http_port)
{
i = sendto (s, buf, len, flags, to, tolen);
return i;
}
memset (buf2, '\0', sizeof (buf2));
memcpy (buf2, &len, sizeof (int));
memcpy (buf2 + sizeof (int), buf, len);
i = send (s, (char *) buf2, len + sizeof (int), 0); /* use TCP connection to proxy */
if (i > 0)
i = i - sizeof (int);
return i;
}
syntax highlighted by Code2HTML, v. 0.9.1