implements Disconnect-Peer-Request (DPR) handling and more proper (?) TLS connection shutdown.

git-svn-id: http://svn.berlios.de/svnroot/repos/sems/trunk@1225 8eb893ce-cfd4-0310-b710-fb5ebe64c474
sayer/1.4-spce2.6
Stefan Sayer 18 years ago
parent 1e906a0ad4
commit 96f41c1c2e

@ -1,16 +1,16 @@
/*
* $Id$
*
* Copyright (C) 2007-2008 IPTEGO GmbH
* Copyright (C) 2007-2009 IPTEGO GmbH
*
* This file is part of sems, a free SIP media server.
* This file is part of SEMS, a free SIP media server.
*
* sems 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
*
* For a license to use the ser software under conditions
* For a license to use the SEMS software under conditions
* other than those described here, or to purchase support for this
* software, please contact iptel.org by e-mail at the following addresses:
* info@iptel.org
@ -20,11 +20,12 @@
* 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
* 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
*/
#include "DiameterClient.h"
#include "log.h"
@ -165,9 +166,77 @@ void DiameterClient::invoke(const string& method, const AmArg& args,
row.assertArrayFmt("iiib");
}
sendRequest(args, ret);
} else if(method == "test1"){
AmArg a;
a.push(AmArg("vtm"));
// a.push(AmArg("10.1.0.196"));
// a.push(AmArg(8080));
a.push(AmArg("62.220.31.182"));
a.push(AmArg(9381));
// a.push(AmArg("127.0.0.1"));
// a.push(AmArg(4433));
a.push(AmArg("vtm01"));
a.push(AmArg("vtm.t-online.de"));
a.push(AmArg("10.42.32.13"));
a.push(AmArg(16777241));
a.push(AmArg(29631));
a.push(AmArg("vtm"));
a.push(AmArg(20)); // timeout
// a.push(AmArg("ca.pem"));
// a.push(AmArg("client.pem"));
newConnection(a, ret);
} else if(method == "test2"){
AmArg a;
#define AAA_APP_USPI 16777241
#define AVP_E164_NUMBER 1024
#define AAA_VENDOR_IPTEGO 29631
#define AAA_LAR 16777214
a.push(AmArg("vtm"));
a.push(AmArg(AAA_LAR));
a.push(AmArg(AAA_APP_USPI));
DBG("x pushin \n");
AmArg avps;
AmArg e164;
e164.push((int)AVP_E164_NUMBER);
e164.push((int)AAA_AVP_FLAG_VENDOR_SPECIFIC | AAA_AVP_FLAG_MANDATORY);
e164.push((int)AAA_VENDOR_IPTEGO);
string e164_number = "+49331600001";
e164.push(ArgBlob(e164_number.c_str(), e164_number.length()));
avps.push(e164);
AmArg drealm;
drealm.push((int)AVP_Destination_Realm);
drealm.push((int)AAA_AVP_FLAG_MANDATORY);
drealm.push((int)0);
string dest_realm = "iptego.de";
drealm.push(ArgBlob(dest_realm.c_str(), dest_realm.length()));
avps.push(drealm);
a.push(avps);
a.push(AmArg("bogus_link"));
// check...
DBG("x checking\n");
a.assertArrayFmt("siias");
DBG("x checking\n");
// check values
AmArg& vals = a.get(3);
for (size_t i=0;i<vals.size(); i++) {
AmArg& row = vals.get(i);
// [int avp_id, int flags, int vendor, blob data]
row.assertArrayFmt("iiib");
}
DBG("x sendrequest\n");
sendRequest(a, ret);
} else if(method == "_list"){
ret.push(AmArg("newConnection"));
ret.push(AmArg("sendRequest"));
ret.push(AmArg("test1"));
ret.push(AmArg("test2"));
} else
throw AmDynInvoke::NotImplemented(method);
}

@ -1,16 +1,16 @@
/*
* $Id$
*
* Copyright (C) 2007-2008 IPTEGO GmbH
* Copyright (C) 2007-2009 IPTEGO GmbH
*
* This file is part of sems, a free SIP media server.
* This file is part of SEMS, a free SIP media server.
*
* sems 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
*
* For a license to use the ser software under conditions
* For a license to use the SEMS software under conditions
* other than those described here, or to purchase support for this
* software, please contact iptel.org by e-mail at the following addresses:
* info@iptel.org
@ -20,10 +20,11 @@
* 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
* 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
*/
#ifndef _DIAMETER_CLIENT_H
#define _DIAMETER_CLIENT_H

@ -1,16 +1,16 @@
/*
* $Id$
*
* Copyright (C) 2007-2008 IPTEGO GmbH
* Copyright (C) 2007-2009 IPTEGO GmbH
*
* This file is part of sems, a free SIP media server.
* This file is part of SEMS, a free SIP media server.
*
* sems 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
*
* For a license to use the ser software under conditions
* For a license to use the SEMS software under conditions
* other than those described here, or to purchase support for this
* software, please contact iptel.org by e-mail at the following addresses:
* info@iptel.org
@ -20,8 +20,8 @@
* 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
* 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
*/
@ -62,8 +62,11 @@ DiameterServerConnection::DiameterServerConnection()
}
void DiameterServerConnection::terminate() {
void DiameterServerConnection::terminate(bool tls_shutdown) {
if (dia_conn) {
if (tls_shutdown)
tcp_tls_shutdown(dia_conn);
tcp_close_connection(dia_conn);
tcp_destroy_connection(dia_conn);
dia_conn = NULL;
@ -244,37 +247,48 @@ void ServerConnection::openConnection() {
AAAFreeMessage(&cer);
int res = tcp_recv_msg(conn.dia_conn, &conn.rb,
unsigned int cea_receive_cnt = 3;
while (true) {
int res = tcp_recv_msg(conn.dia_conn, &conn.rb,
CONNECT_CEA_REPLY_TIMEOUT, 0);
if (res <= 0) {
if (!res) {
ERROR( " openConnection(): did not receive response (CEA).\n");
} else {
ERROR( " openConnection(): error receiving response (CEA).\n");
if (res <= 0) {
if (!res) {
ERROR( " openConnection(): did not receive response (CEA).\n");
} else {
ERROR( " openConnection(): error receiving response (CEA).\n");
}
conn.terminate();
setRetryConnectLater();
return;
}
/* obtain the structure corresponding to the message */
AAAMessage* cea = AAATranslateMessage(conn.rb.buf, conn.rb.buf_len, 0);
if(!cea) {
ERROR( " openConnection(): could not decipher response (CEA).\n");
conn.terminate();
setRetryConnectLater();
return;
}
conn.terminate();
setRetryConnectLater();
return;
}
/* obtain the structure corresponding to the message */
AAAMessage* cea = AAATranslateMessage(conn.rb.buf, conn.rb.buf_len, 0);
if(!cea) {
ERROR( " openConnection(): could not decipher response (CEA).\n");
conn.terminate();
setRetryConnectLater();
return;
}
// assume its CEA....
if (cea->commandCode == AAA_CC_CEA) {
#ifdef EXTRA_DEBUG
if (cea != NULL)
AAAPrintMessage(cea);
AAAPrintMessage(cea);
#endif
AAAFreeMessage(&cea);
break;
}
AAAFreeMessage(&cea);
AAAFreeMessage(&cea);
if (!(cea_receive_cnt--)) {
ERROR( " openConnection(): no CEA received.\n");
conn.terminate();
setRetryConnectLater();
return;
}
}
DBG("Connection opened.\n");
open = true;
@ -425,6 +439,7 @@ int ServerConnection::handleRequest(AAAMessage* req) {
AAAMessageSetReply(reply);
if (addOrigin(reply) || addResultCodeAVP(reply, AAA_SUCCESS)) {
AAAFreeMessage(&reply);
return AAA_ERROR_MESSAGE;
}
@ -451,7 +466,62 @@ int ServerConnection::handleRequest(AAAMessage* req) {
}; break;
case AAA_CC_DPR: { // Disconnect-Peer-Request
DBG("Disconnect-Peer-Request not yet implemented\n");
string disconnect_cause = "UNKNOWN";
AAA_AVP* avp = req->avpList.head;
while (avp) {
if (avp->code == AVP_Disconnect_Cause) {
switch((unsigned int)htonl(*((unsigned int*)avp->data.s))){
case 0:disconnect_cause = "REBOOTING"; break;
case 1:disconnect_cause = "BUSY"; break;
case 2:disconnect_cause = "DO_NOT_WANT_TO_TALK_TO_YOU"; break;
}
break;
}
avp=avp->next;
}
DBG("Disconnect-Peer-Request received. Cause: '%s'."
" Sending Disconnect-Peer-Answer...\n", disconnect_cause.c_str());
AAAMessage* reply;
if ( (reply=AAAInMessage(AAA_CC_DPA, AAA_APP_DIAMETER_COMMON_MSG))==NULL) {
ERROR(M_NAME":handleRequest(): can't create new "
"DPA message!\n");
return AAA_ERROR_MESSAGE;
}
AAAMessageSetReply(reply);
// always send success (causing retry of requests on
// different connection first, so race is unlikely)
if (addOrigin(reply) || addResultCodeAVP(reply, AAA_SUCCESS)) {
AAAFreeMessage(&reply);
return AAA_ERROR_MESSAGE;
}
reply->endtoendId = req->endtoendId;
reply->hopbyhopId = req->hopbyhopId;
if(AAABuildMsgBuffer(reply) != AAA_ERR_SUCCESS) {
ERROR( " sendRequest(): message buffer not created\n");
AAAFreeMessage(&reply);
return AAA_ERROR_MESSAGE;
}
int ret = tcp_send(conn.dia_conn, reply->buf.s, reply->buf.len);
if (ret) {
ERROR( " sendRequest(): could not send message\n");
closeConnection();
AAAFreeMessage(&reply);
return AAA_ERROR_COMM;
}
AAAFreeMessage(&reply);
setRetryConnectLater();
return 0;
}; break;
default: {
@ -538,9 +608,15 @@ void ServerConnection::receive() {
int res = tcp_recv_msg(conn.dia_conn, &conn.rb,
0, CONN_WAIT_USECS);
if (res < 0) {
ERROR( M_NAME "receive(): tcp_recv_reply() failed.\n");
closeConnection();
if (res == AAA_CONN_SHUTDOWN) {
INFO( M_NAME "receive(): shutdown - closing connection.\n");
closeConnection(true);
} else {
closeConnection();
ERROR( M_NAME "receive(): tcp_recv_reply() failed.\n");
}
return;
}
@ -634,7 +710,7 @@ void ServerConnection::checkTimeouts() {
void ServerConnection::shutdownConnection() {
gettimeofday(&connect_ts, NULL);
connect_ts.tv_sec += RETRY_CONNECTION_SYSERROR;
closeConnection();
closeConnection(true);
req_map_mut.lock();
DBG("shutdown: posting timeout to %zd pending requests....\n",
@ -652,8 +728,8 @@ void ServerConnection::shutdownConnection() {
req_map_mut.unlock();
}
void ServerConnection::closeConnection() {
void ServerConnection::closeConnection(bool tls_shutdown) {
if (open)
conn.terminate();
conn.terminate(tls_shutdown);
open = false;
}

@ -1,16 +1,16 @@
/*
* $Id$
*
* Copyright (C) 2007-2008 IPTEGO GmbH
* Copyright (C) 2007-2009 IPTEGO GmbH
*
* This file is part of sems, a free SIP media server.
* This file is part of SEMS, a free SIP media server.
*
* sems 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
*
* For a license to use the ser software under conditions
* For a license to use the SEMS software under conditions
* other than those described here, or to purchase support for this
* software, please contact iptel.org by e-mail at the following addresses:
* info@iptel.org
@ -20,10 +20,11 @@
* 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
* 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
*/
#ifndef _DIAMETER_SERVER_CONNECTION_H
#define _DIAMETER_SERVER_CONNECTION_H
@ -81,7 +82,7 @@ struct DiameterServerConnection {
AAAMsgIdentifier h2h;
AAAMsgIdentifier e2e;
void terminate();
void terminate(bool tls_shutdown = false);
void setIDs(AAAMessage* msg);
@ -125,7 +126,7 @@ class ServerConnection
AmMutex req_map_mut;
void openConnection();
void closeConnection();
void closeConnection(bool tls_shutdown = false);
int addOrigin(AAAMessage* msg);

@ -22,9 +22,11 @@
#define AAA_NOT_AUTHORIZED 2
#define AAA_SRVERR 3
#define AAA_ERROR -1
#define AAA_ERROR -1
#define AAA_CONN_CLOSED -2
#define AAA_TIMEOUT -3
#define AAA_TIMEOUT -3
#define AAA_CONN_SHUTDOWN -2
#define AAA_USER_IN_GROUP 0
#define AAA_NO_CONNECTION -1

@ -4,6 +4,7 @@
* 2003-04-07 created by bogdan
*
* Copyright (C) 2002-2003 FhG Fokus
* Copyright (C) 2007-2009 IPTEGO GmbH
*
* This file is part of disc, a free diameter server/client.
*

@ -4,6 +4,7 @@
* 2003-04-07 created by bogdan
*
* Copyright (C) 2002-2003 FhG Fokus
* Copyright (C) 2007-2009 IPTEGO GmbH
*
* This file is part of disc, a free diameter server/client.
*

@ -4,7 +4,7 @@
* Digest Authentication - Diameter support
*
* Copyright (C) 2001-2003 FhG Fokus
* Copyright (C) 2007 iptego GmbH
* Copyright (C) 2007-2009 iptego GmbH
*
* This file is part of ser, a free SIP server.
*
@ -195,9 +195,20 @@ dia_tcp_conn* tcp_create_connection(const char* host, int port,
meth=TLSv1_client_method();
conn_st->ctx = SSL_CTX_new(meth);
if (!conn_st->ctx) {
ERROR("SSL: creating TLSv1_client_method context\n");
return 0;
}
if (SSL_CTX_set_default_verify_paths(conn_st->ctx) != 1) {
ERROR("SSL: SSL_CTX_set_default_verify_paths\n");
return 0;
}
if (!strlen(client_cert_file)) {
DBG("no client certificate - not authenticating client.\n");
} else {
if (!SSL_CTX_use_certificate_chain_file(conn_st->ctx, client_cert_file)) {
ERROR("using certificate from file '%s'\n",
client_cert_file);
@ -249,6 +260,15 @@ dia_tcp_conn* tcp_create_connection(const char* host, int port,
return conn_st;
}
void tcp_tls_shutdown(dia_tcp_conn* conn_st) {
#ifdef WITH_OPENSSL
if (conn_st->ctx && conn_st->ssl) {
SSL_shutdown(conn_st->ssl);
}
#endif
}
void reset_read_buffer(rd_buf_t *rb)
{
rb->ret_code = 0;
@ -516,8 +536,8 @@ int tcp_recv_msg(dia_tcp_conn* conn_st, rd_buf_t* rb,
ERROR( M_NAME":tcp_reply_recv(): error when trying to read from socket\n");
return AAA_CONN_CLOSED;
case CONN_CLOSED:
ERROR( M_NAME":tcp_reply_recv(): connection closed by diameter peer\n");
return AAA_CONN_CLOSED;
INFO( M_NAME":tcp_reply_recv(): connection closed by diameter peer\n");
return AAA_CONN_SHUTDOWN;
}
return 1; //received something
}

@ -4,7 +4,7 @@
* Digest Authentication - Diameter support
*
* Copyright (C) 2001-2003 FhG Fokus
* Copyright (C) 2008 iptego GmbH
* Copyright (C) 2008-2009 iptego GmbH
*
* This file is part of ser, a free SIP server.
*
@ -54,6 +54,7 @@
#define CONN_ERROR -1
#define CONN_CLOSED -2
#ifdef __cplusplus
extern "C" {
#endif
@ -92,6 +93,7 @@ extern "C" {
void tcp_destroy_connection(dia_tcp_conn* conn_st);
void tcp_tls_shutdown(dia_tcp_conn* conn_st);
#ifdef __cplusplus
}
#endif

Loading…
Cancel
Save