blob: 7fa5a7d19915d74d83462939bd012d1e8cf893b0 [file] [log] [blame]
/* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
*
* @author Mladen Turk
* @version $Id: address.c 1442587 2013-02-05 13:49:48Z rjung $
*/
#include "tcn.h"
TCN_IMPLEMENT_CALL(jlong, Address, info)(TCN_STDARGS,
jstring hostname,
jint family, jint port,
jint flags, jlong pool)
{
apr_pool_t *p = J2P(pool, apr_pool_t *);
TCN_ALLOC_CSTRING(hostname);
char *sp = NULL;
int scope_id = 0;
apr_sockaddr_t *sa = NULL;
apr_sockaddr_t *sl = NULL;
apr_int32_t f;
UNREFERENCED(o);
GET_S_FAMILY(f, family);
#if APR_HAVE_IPV6
if (hostname) {
/* XXX: This only works for real scope_id's
*/
if ((sp = strchr(J2S(hostname), '%'))) {
*sp++ = '\0';
scope_id = atoi(sp);
}
}
#endif
TCN_THROW_IF_ERR(apr_sockaddr_info_get(&sa,
J2S(hostname), f, (apr_port_t)port,
(apr_int32_t)flags, p), sa);
sl = sa;
/*
* apr_sockaddr_info_get may return several address so this is not
* go to work in some cases (but as least it works for Linux)
* XXX: with AP_ENABLE_V4_MAPPED it is going to work otherwise it won't.
*/
#if APR_HAVE_IPV6
if (hostname == NULL) {
/* Try all address using IPV6 one */
while (sl) {
if (sl->family == APR_INET6)
break; /* Done */
sl = sl->next;
}
/* If we don't find an IPv6 address, use the original one */
if (sl == NULL) {
sl = sa;
}
}
if (sp) {
/* Set the provided scope id
* APR lack the api for setting this directly so lets presume
* the sin6_scope_id is present everywhere
*/
sl->sa.sin6.sin6_scope_id = scope_id;
}
#endif
cleanup:
TCN_FREE_CSTRING(hostname);
return P2J(sl);
}
TCN_IMPLEMENT_CALL(jstring, Address, getnameinfo)(TCN_STDARGS,
jlong sa, jint flags)
{
apr_sockaddr_t *s = J2P(sa, apr_sockaddr_t *);
char *hostname;
UNREFERENCED(o);
if (apr_getnameinfo(&hostname, s, (apr_int32_t)flags) == APR_SUCCESS)
return AJP_TO_JSTRING(hostname);
else
return NULL;
}
TCN_IMPLEMENT_CALL(jstring, Address, getip)(TCN_STDARGS, jlong sa)
{
apr_sockaddr_t *s = J2P(sa, apr_sockaddr_t *);
char *ipaddr;
UNREFERENCED(o);
if (apr_sockaddr_ip_get(&ipaddr, s) == APR_SUCCESS)
return AJP_TO_JSTRING(ipaddr);
else
return NULL;
}
TCN_IMPLEMENT_CALL(jlong, Address, get)(TCN_STDARGS, jint which,
jlong sock)
{
tcn_socket_t *s = J2P(sock, tcn_socket_t *);
apr_sockaddr_t *sa = NULL;
UNREFERENCED(o);
TCN_THROW_IF_ERR(apr_socket_addr_get(&sa,
(apr_interface_e)which, s->sock), sa);
cleanup:
return P2J(sa);
}
TCN_IMPLEMENT_CALL(jboolean, Address, equal)(TCN_STDARGS,
jlong a, jlong b)
{
apr_sockaddr_t *sa = J2P(a, apr_sockaddr_t *);
apr_sockaddr_t *sb = J2P(b, apr_sockaddr_t *);
UNREFERENCED_STDARGS;
return apr_sockaddr_equal(sa, sb) ? JNI_TRUE : JNI_FALSE;
}
TCN_IMPLEMENT_CALL(jint, Address, getservbyname)(TCN_STDARGS,
jlong sa, jstring servname)
{
apr_sockaddr_t *s = J2P(sa, apr_sockaddr_t *);
TCN_ALLOC_CSTRING(servname);
apr_status_t rv;
UNREFERENCED(o);
rv = apr_getservbyname(s, J2S(servname));
TCN_FREE_CSTRING(servname);
return (jint)rv;
}