Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
oai
freediameter
Commits
aa61f58e
Commit
aa61f58e
authored
Oct 02, 2009
by
Sebastien Decugis
Browse files
Started including TLS code
parent
8d95d265
Changes
7
Hide whitespace changes
Inline
Side-by-side
freeDiameter/CMakeLists.txt
View file @
aa61f58e
...
...
@@ -26,6 +26,10 @@ SET(FD_COMMON_GEN_SRC
fdd.tab.h
)
# Require GNU TLS for building the daemon
FIND_PACKAGE
(
GNUTLS REQUIRED
)
INCLUDE_DIRECTORIES
(
${
GNUTLS_INCLUDE_DIRS
}
)
SET
(
FD_LIBS
${
FD_LIBS
}
${
GNUTLS_LIBRARIES
}
)
# Building the executable
ADD_EXECUTABLE
(
freeDiameterd
${
FD_COMMON_SRC
}
${
FD_COMMON_GEN_SRC
}
main.c
)
...
...
freeDiameter/fD.h
View file @
aa61f58e
...
...
@@ -150,11 +150,11 @@ struct fd_peer { /* The "real" definition of the peer structure */
/* Events codespace for struct fd_peer->p_events */
enum
{
/* request to terminate this peer : disconnect, requeue all messages */
FDEVP_TERMINATE
=
2000
/* Dump all info about this peer in the debug log */
,
FDEVP_DUMP_ALL
FDEVP_DUMP_ALL
=
2000
/* request to terminate this peer : disconnect, requeue all messages */
,
FDEVP_TERMINATE
/* A message was received in the peer */
,
FDEVP_MSG_INCOMING
...
...
@@ -163,6 +163,8 @@ enum {
,
FDEVP_PSM_TIMEOUT
};
const
char
*
fd_pev_str
(
int
event
);
#define CHECK_EVENT( _e ) \
(((int)(_e) >= FDEVP_DUMP_ALL) && ((int)(_e) <= FDEVP_PSM_TIMEOUT))
/* Structure to store a sent request */
struct
sentreq
{
...
...
@@ -173,6 +175,9 @@ struct sentreq {
/* Functions */
int
fd_peer_fini
();
void
fd_peer_dump_list
(
int
details
);
void
fd_peer_dump
(
struct
fd_peer
*
peer
,
int
details
);
int
fd_peer_alloc
(
struct
fd_peer
**
ptr
);
int
fd_peer_free
(
struct
fd_peer
**
ptr
);
/* fd_peer_add declared in freeDiameter.h */
/* Peer expiry */
...
...
freeDiameter/main.c
View file @
aa61f58e
...
...
@@ -37,6 +37,12 @@
#include <signal.h>
#include <getopt.h>
#include <locale.h>
#ifdef GCRY_THREAD_OPTION_PTHREAD_IMPL
GCRY_THREAD_OPTION_PTHREAD_IMPL
;
#endif
/* GCRY_THREAD_OPTION_PTHREAD_IMPL */
/* forward declarations */
static
void
*
sig_hdl
(
void
*
arg
);
...
...
@@ -61,6 +67,7 @@ int main(int argc, char * argv[])
/* Initialize the library */
CHECK_FCT
(
fd_lib_init
()
);
TRACE_DEBUG
(
INFO
,
"libfreeDiameter initialized."
);
/* Name this thread */
fd_log_threadname
(
"Main"
);
...
...
@@ -71,6 +78,15 @@ int main(int argc, char * argv[])
/* Parse the command-line */
CHECK_FCT
(
main_cmdline
(
argc
,
argv
)
);
/* Initialize gnutls */
CHECK_GNUTLS_DO
(
gnutls_global_init
(),
return
EINVAL
);
if
(
!
gnutls_check_version
(
GNUTLS_VERSION
)
)
{
fprintf
(
stderr
,
"The GNUTLS library is too old; found '%s', need '"
GNUTLS_VERSION
"'
\n
"
,
gnutls_check_version
(
NULL
));
return
EINVAL
;
}
else
{
TRACE_DEBUG
(
INFO
,
"GNUTLS library '%s' initialized."
,
gnutls_check_version
(
NULL
));
}
/* Allow SIGINT and SIGTERM from this point */
CHECK_POSIX
(
pthread_create
(
&
sig_th
,
NULL
,
sig_hdl
,
NULL
)
);
...
...
@@ -141,6 +157,8 @@ end:
CHECK_FCT_DO
(
fd_thr_term
(
&
sig_th
),
/* continue */
);
gnutls_global_deinit
();
return
ret
;
}
...
...
@@ -167,21 +185,23 @@ static int main_cmdline(int argc, char *argv[])
{
int
c
;
int
option_index
=
0
;
char
*
locale
;
struct
option
long_options
[]
=
{
{
"help"
,
0
,
NULL
,
'h'
},
{
"version"
,
0
,
NULL
,
'V'
},
{
"config"
,
1
,
NULL
,
'c'
},
{
"debug"
,
0
,
NULL
,
'd'
},
{
"quiet"
,
0
,
NULL
,
'q'
},
{
NULL
,
0
,
NULL
,
0
}
{
"help"
,
no_argument
,
NULL
,
'h'
},
{
"version"
,
no_argument
,
NULL
,
'V'
},
{
"config"
,
required_argument
,
NULL
,
'c'
},
{
"debug"
,
no_argument
,
NULL
,
'd'
},
{
"quiet"
,
no_argument
,
NULL
,
'q'
},
{
"dbglocale"
,
optional_argument
,
NULL
,
'l'
},
{
NULL
,
0
,
NULL
,
0
}
};
TRACE_ENTRY
(
"%d %p"
,
argc
,
argv
);
/* Loop on arguments */
while
(
1
)
{
c
=
getopt_long
(
argc
,
argv
,
"hVc:dq"
,
long_options
,
&
option_index
);
c
=
getopt_long
(
argc
,
argv
,
"hVc:dq
l:
"
,
long_options
,
&
option_index
);
if
(
c
==
-
1
)
break
;
/* Exit from the loop. */
...
...
@@ -199,6 +219,16 @@ static int main_cmdline(int argc, char *argv[])
fd_g_config
->
cnf_file
=
optarg
;
break
;
case
'l'
:
/* Change the locale. */
locale
=
setlocale
(
LC_ALL
,
optarg
?:
""
);
if
(
locale
)
{
TRACE_DEBUG
(
INFO
,
"Locale set to: %s"
,
optarg
?:
locale
);
}
else
{
TRACE_DEBUG
(
INFO
,
"Unable to set locale (%s)"
,
optarg
);
return
EINVAL
;
}
break
;
case
'd'
:
/* Increase verbosity of debug messages. */
fd_g_debug_lvl
++
;
break
;
...
...
@@ -209,11 +239,11 @@ static int main_cmdline(int argc, char *argv[])
case
'?'
:
/* Invalid option. */
/* `getopt_long' already printed an error message. */
TRACE_DEBUG
(
INFO
,
"getopt_long found an invalid character
\n
"
);
TRACE_DEBUG
(
INFO
,
"getopt_long found an invalid character"
);
return
EINVAL
;
default:
/* bug: option not considered. */
TRACE_DEBUG
(
INFO
,
"A command-line option is missing in parser: %c
\n
"
,
c
);
TRACE_DEBUG
(
INFO
,
"A command-line option is missing in parser: %c"
,
c
);
ASSERT
(
0
);
return
EINVAL
;
}
...
...
@@ -266,6 +296,7 @@ static void main_help( void )
" default location (%s).
\n
"
,
DEFAULT_CONF_FILE
);
printf
(
"
\n
Debug:
\n
"
" These options are mostly useful for developers
\n
"
" -l, --dbglocale Set the locale for error messages
\n
"
" -d, --debug Increase verbosity of debug messages
\n
"
" -q, --quiet Decrease verbosity then remove debug messages
\n
"
);
}
...
...
freeDiameter/p_expiry.c
View file @
aa61f58e
...
...
@@ -35,11 +35,63 @@
#include "fD.h"
/* Delay for garbage collection of expired threads, in seconds */
#define GC_TIME 60
static
pthread_t
exp_thr
;
static
pthread_t
gc_thr
;
static
struct
fd_list
exp_list
=
FD_LIST_INITIALIZER
(
exp_list
);
static
pthread_cond_t
exp_cnd
=
PTHREAD_COND_INITIALIZER
;
static
pthread_mutex_t
exp_mtx
=
PTHREAD_MUTEX_INITIALIZER
;
static
void
*
gc_th_fct
(
void
*
arg
)
{
fd_log_threadname
(
"Peers/garbage"
);
TRACE_ENTRY
(
""
);
do
{
struct
fd_list
*
li
,
purge
=
FD_LIST_INITIALIZER
(
purge
);
pthread_testcancel
();
sleep
(
GC_TIME
);
/* Now check in the peers list if any peer can be deleted */
CHECK_FCT_DO
(
pthread_rwlock_wrlock
(
&
fd_g_peers_rw
),
goto
error
);
for
(
li
=
fd_g_peers
.
next
;
li
!=
&
fd_g_peers
;
li
=
li
->
next
)
{
struct
fd_peer
*
peer
=
(
struct
fd_peer
*
)
li
;
if
(
peer
->
p_hdr
.
info
.
pi_state
!=
STATE_ZOMBIE
)
continue
;
if
(
peer
->
p_hdr
.
info
.
pi_flags
.
exp
==
PI_EXP_NONE
)
continue
;
/* This peer was not supposed to expire, keep it in the list */
/* Ok, the peer was expired, let's remove it */
li
=
li
->
prev
;
/* to avoid breaking the loop */
fd_list_unlink
(
&
peer
->
p_hdr
.
chain
);
fd_list_insert_before
(
&
purge
,
&
peer
->
p_hdr
.
chain
);
}
CHECK_FCT_DO
(
pthread_rwlock_unlock
(
&
fd_g_peers_rw
),
goto
error
);
/* Now delete peers that are in the purge list */
while
(
!
FD_IS_LIST_EMPTY
(
&
purge
))
{
struct
fd_peer
*
peer
=
(
struct
fd_peer
*
)(
purge
.
next
);
fd_list_unlink
(
&
peer
->
p_hdr
.
chain
);
TRACE_DEBUG
(
INFO
,
"Garbage Collect: delete zombie peer '%s'"
,
peer
->
p_hdr
.
info
.
pi_diamid
);
CHECK_FCT_DO
(
fd_peer_free
(
&
peer
),
/* Continue... what else to do ? */
);
}
}
while
(
1
);
error:
TRACE_DEBUG
(
INFO
,
"An error occurred in peers module! GC thread is terminating..."
);
ASSERT
(
0
);
CHECK_FCT_DO
(
fd_event_send
(
fd_g_config
->
cnf_main_ev
,
FDEV_TERMINATE
,
NULL
),
);
return
NULL
;
}
static
void
*
exp_th_fct
(
void
*
arg
)
{
fd_log_threadname
(
"Peers/expire"
);
...
...
@@ -97,6 +149,7 @@ int fd_p_expi_init(void)
{
TRACE_ENTRY
();
CHECK_FCT
(
pthread_create
(
&
exp_thr
,
NULL
,
exp_th_fct
,
NULL
)
);
CHECK_FCT
(
pthread_create
(
&
gc_thr
,
NULL
,
gc_th_fct
,
NULL
)
);
return
0
;
}
...
...
@@ -112,6 +165,7 @@ int fd_p_expi_fini(void)
}
CHECK_POSIX
(
pthread_mutex_unlock
(
&
exp_mtx
)
);
CHECK_FCT_DO
(
fd_thr_term
(
&
gc_thr
),
);
return
0
;
}
...
...
freeDiameter/p_psm.c
View file @
aa61f58e
...
...
@@ -36,7 +36,7 @@
#include "fD.h"
const
char
*
peer_state_str
[]
=
{
"STATE_
ZOMBIE
"
"STATE_
NEW
"
,
"STATE_OPEN"
,
"STATE_CLOSED"
,
"STATE_CLOSING"
...
...
@@ -45,6 +45,7 @@ const char *peer_state_str[] = {
,
"STATE_WAITCEA"
,
"STATE_SUSPECT"
,
"STATE_REOPEN"
,
"STATE_ZOMBIE"
};
const
char
*
fd_pev_str
(
int
event
)
...
...
@@ -122,6 +123,7 @@ static void psm_next_timeout(struct fd_peer * peer, int add_random, int delay)
#endif
}
/* Wait for the next event in the PSM, or timeout */
static
int
psm_ev_timedget
(
struct
fd_peer
*
peer
,
int
*
code
,
void
**
data
)
{
struct
fd_event
*
ev
;
...
...
@@ -141,13 +143,15 @@ static int psm_ev_timedget(struct fd_peer * peer, int *code, void ** data)
}
return
0
;
}
}
/* The state machine thread */
/* The state machine thread
(controler)
*/
static
void
*
p_psm_th
(
void
*
arg
)
{
struct
fd_peer
*
peer
=
(
struct
fd_peer
*
)
arg
;
int
created_started
=
started
;
int
event
;
void
*
ev_data
;
CHECK_PARAMS_DO
(
CHECK_PEER
(
peer
),
ASSERT
(
0
)
);
...
...
@@ -160,12 +164,12 @@ static void * p_psm_th( void * arg )
fd_log_threadname
(
buf
);
}
/* Wait that the PSM are authorized to start in the daemon */
CHECK_FCT_DO
(
fd_psm_waitstart
(),
goto
end
);
/* The state machine starts in CLOSED state */
peer
->
p_hdr
.
info
.
pi_state
=
STATE_CLOSED
;
/* Wait that the PSM are authorized to start in the daemon */
CHECK_FCT_DO
(
fd_psm_waitstart
(),
goto
psm_end
);
/* Initialize the timer */
if
(
peer
->
p_flags
.
pf_responder
)
{
psm_next_timeout
(
peer
,
0
,
INCNX_TIMEOUT
);
...
...
@@ -173,27 +177,68 @@ static void * p_psm_th( void * arg )
psm_next_timeout
(
peer
,
created_started
?
0
:
1
,
0
);
}
psm:
do
{
int
event
;
void
*
ev_data
;
/* Get next event */
CHECK_FCT_DO
(
psm_ev_timedget
(
peer
,
&
event
,
&
ev_data
),
goto
end
);
TRACE_DEBUG
(
FULL
,
"'%s'
\t
<-- '%s'
\t
(%p)
\t
'%s'"
,
STATE_STR
(
peer
->
p_hdr
.
info
.
pi_state
),
fd_pev_str
(
event
),
ev_data
,
peer
->
p_hdr
.
info
.
pi_diamid
);
/* Now, the action depends on the current state and the incoming event */
psm_loop:
/* Get next event */
CHECK_FCT_DO
(
psm_ev_timedget
(
peer
,
&
event
,
&
ev_data
),
goto
psm_end
);
TRACE_DEBUG
(
FULL
,
"'%s'
\t
<-- '%s'
\t
(%p)
\t
'%s'"
,
STATE_STR
(
peer
->
p_hdr
.
info
.
pi_state
),
fd_pev_str
(
event
),
ev_data
,
peer
->
p_hdr
.
info
.
pi_diamid
);
/* Now, the action depends on the current state and the incoming event */
/* The following two states are impossible */
ASSERT
(
peer
->
p_hdr
.
info
.
pi_state
!=
STATE_NEW
);
ASSERT
(
peer
->
p_hdr
.
info
.
pi_state
!=
STATE_ZOMBIE
);
/* Purge invalid events */
if
(
!
CHECK_EVENT
(
event
))
{
TRACE_DEBUG
(
INFO
,
"Invalid event received in PSM '%s' : %d"
,
peer
->
p_hdr
.
info
.
pi_diamid
,
event
);
goto
psm_loop
;
}
/* Handle the (easy) debug event now */
if
(
event
==
FDEVP_DUMP_ALL
)
{
fd_peer_dump
(
peer
,
ANNOYING
);
goto
psm_loop
;
}
/* Requests to terminate the peer object */
if
(
event
==
FDEVP_TERMINATE
)
{
switch
(
peer
->
p_hdr
.
info
.
pi_state
)
{
case
STATE_CLOSING
:
case
STATE_WAITCNXACK
:
case
STATE_WAITCNXACK_ELEC
:
case
STATE_WAITCEA
:
case
STATE_SUSPECT
:
/* In these cases, we just cleanup the peer object and terminate now */
TODO
(
"Cleanup the PSM: terminate connection object, ..."
);
case
STATE_CLOSED
:
/* Then we just terminate the PSM */
goto
psm_end
;
case
STATE_OPEN
:
case
STATE_REOPEN
:
/* We cannot just close the conenction, we have to send a DPR first */
TODO
(
"Send DPR, mark the peer as CLOSING"
);
goto
psm_loop
;
}
}
}
while
(
1
);
/* MSG_RECEIVED: fd_p_expi_update(struct fd_peer * peer ) */
/* If timeout or OPEN : call cb if defined */
/* Default action : the handling has not yet been implemented. */
TODO
(
"Missing handler in PSM : '%s'
\t
<-- '%s'"
,
STATE_STR
(
peer
->
p_hdr
.
info
.
pi_state
),
fd_pev_str
(
event
));
if
(
event
==
FDEVP_PSM_TIMEOUT
)
{
/* We have not handled timeout in this state, let's postpone next alert */
psm_next_timeout
(
peer
,
0
,
60
);
}
goto
psm_loop
;
end:
/* set STATE_ZOMBIE */
pthread_cleanup_pop
(
1
);
psm_end:
pthread_cleanup_pop
(
1
);
/* set STATE_ZOMBIE */
return
NULL
;
}
...
...
@@ -204,8 +249,15 @@ end:
int
fd_psm_begin
(
struct
fd_peer
*
peer
)
{
TRACE_ENTRY
(
"%p"
,
peer
);
TODO
(
""
);
return
ENOTSUP
;
/* Check the peer and state are OK */
CHECK_PARAMS
(
CHECK_PEER
(
peer
)
&&
(
peer
->
p_hdr
.
info
.
pi_state
==
STATE_NEW
)
);
/* Create the PSM controler thread */
CHECK_POSIX
(
pthread_create
(
&
peer
->
p_psm
,
NULL
,
p_psm_th
,
peer
)
);
/* We're done */
return
0
;
}
/* End the PSM (clean ending) */
...
...
@@ -213,7 +265,11 @@ int fd_psm_terminate(struct fd_peer * peer )
{
TRACE_ENTRY
(
"%p"
,
peer
);
CHECK_PARAMS
(
CHECK_PEER
(
peer
)
);
CHECK_FCT
(
fd_event_send
(
peer
->
p_events
,
FDEVP_TERMINATE
,
NULL
)
);
if
(
peer
->
p_hdr
.
info
.
pi_state
!=
STATE_ZOMBIE
)
{
CHECK_FCT
(
fd_event_send
(
peer
->
p_events
,
FDEVP_TERMINATE
,
NULL
)
);
}
else
{
TRACE_DEBUG
(
FULL
,
"Peer '%s' was already terminated"
,
peer
->
p_hdr
.
info
.
pi_diamid
);
}
return
0
;
}
...
...
@@ -224,7 +280,8 @@ void fd_psm_abord(struct fd_peer * peer )
TODO
(
"Cancel PSM thread"
);
TODO
(
"Cancel IN thread"
);
TODO
(
"Cancel OUT thread"
);
TODO
(
"Cleanup the connection"
);
TODO
(
"Cleanup the peer connection object"
);
TODO
(
"Cleanup the message queues (requeue)"
);
return
;
}
...
...
freeDiameter/peers.c
View file @
aa61f58e
...
...
@@ -35,63 +35,13 @@
#include "fD.h"
/* Global list of peers */
struct
fd_list
fd_g_peers
=
FD_LIST_INITIALIZER
(
fd_g_peers
);
pthread_rwlock_t
fd_g_peers_rw
=
PTHREAD_RWLOCK_INITIALIZER
;
/* Terminate peer module (destroy all peers) */
int
fd_peer_fini
()
{
struct
fd_list
*
li
;
TRACE_ENTRY
();
CHECK_FCT_DO
(
fd_p_expi_fini
(),
/* continue */
);
TRACE_DEBUG
(
INFO
,
"Sending signal to terminate to all peer connections"
);
CHECK_FCT_DO
(
pthread_rwlock_rdlock
(
&
fd_g_peers_rw
),
/* continue */
);
/* For each peer in the list, ... */
for
(
li
=
fd_g_peers
.
next
;
li
!=
&
fd_g_peers
;
li
=
li
->
next
)
{
struct
fd_peer
*
np
=
(
struct
fd_peer
*
)
li
;
CHECK_FCT_DO
(
fd_psm_terminate
(
np
),
/* continue */
);
}
CHECK_FCT_DO
(
pthread_rwlock_unlock
(
&
fd_g_peers_rw
),
/* continue */
);
TODO
(
"Give some time to all PSM, then destroy remaining threads"
);
/* fd_psm_abord(struct fd_peer * peer ) */
return
0
;
}
/* Dump the list of peers */
void
fd_peer_dump_list
(
int
details
)
{
struct
fd_list
*
li
;
fd_log_debug
(
"Dumping list of peers :
\n
"
);
CHECK_FCT_DO
(
pthread_rwlock_rdlock
(
&
fd_g_peers_rw
),
/* continue */
);
for
(
li
=
fd_g_peers
.
next
;
li
!=
&
fd_g_peers
;
li
=
li
->
next
)
{
struct
fd_peer
*
np
=
(
struct
fd_peer
*
)
li
;
if
(
np
->
p_eyec
!=
EYEC_PEER
)
{
fd_log_debug
(
" Invalid entry @%p !
\n
"
,
li
);
continue
;
}
fd_log_debug
(
" %s
\t
%s"
,
STATE_STR
(
np
->
p_hdr
.
info
.
pi_state
),
np
->
p_hdr
.
info
.
pi_diamid
);
if
(
details
>
INFO
)
{
fd_log_debug
(
"
\t
(rlm:%s)"
,
np
->
p_hdr
.
info
.
pi_realm
);
if
(
np
->
p_hdr
.
info
.
pi_prodname
)
fd_log_debug
(
"
\t
['%s' %u]"
,
np
->
p_hdr
.
info
.
pi_prodname
,
np
->
p_hdr
.
info
.
pi_firmrev
);
fd_log_debug
(
"
\t
(from %s)"
,
np
->
p_dbgorig
);
}
fd_log_debug
(
"
\n
"
);
}
CHECK_FCT_DO
(
pthread_rwlock_unlock
(
&
fd_g_peers_rw
),
/* continue */
);
}
/* Alloc / reinit a peer structure. if *ptr is not NULL, it must already point to a valid struct fd_peer. */
static
int
fd_sp_reinit
(
struct
fd_peer
**
ptr
)
int
fd_peer_alloc
(
struct
fd_peer
**
ptr
)
{
struct
fd_peer
*
p
;
...
...
@@ -125,6 +75,86 @@ static int fd_sp_reinit(struct fd_peer ** ptr)
return
0
;
}
/* Add a new peer entry */
int
fd_peer_add
(
struct
peer_info
*
info
,
char
*
orig_dbg
,
void
(
*
cb
)(
struct
peer_info
*
,
void
*
),
void
*
cb_data
)
{
struct
fd_peer
*
p
=
NULL
;
struct
fd_list
*
li
;
int
ret
=
0
;
TRACE_ENTRY
(
"%p %p %p %p"
,
info
,
orig_dbg
,
cb
,
cb_data
);
CHECK_PARAMS
(
info
&&
info
->
pi_diamid
);
/* Create a structure to contain the new peer information */
CHECK_FCT
(
fd_peer_alloc
(
&
p
)
);
/* Copy the informations from the parameters received */
CHECK_MALLOC
(
p
->
p_hdr
.
info
.
pi_diamid
=
strdup
(
info
->
pi_diamid
)
);
if
(
info
->
pi_realm
)
{
CHECK_MALLOC
(
p
->
p_hdr
.
info
.
pi_realm
=
strdup
(
info
->
pi_realm
)
);
}
p
->
p_hdr
.
info
.
pi_flags
.
pro3
=
info
->
pi_flags
.
pro3
;
p
->
p_hdr
.
info
.
pi_flags
.
pro4
=
info
->
pi_flags
.
pro4
;
p
->
p_hdr
.
info
.
pi_flags
.
alg
=
info
->
pi_flags
.
alg
;
p
->
p_hdr
.
info
.
pi_flags
.
sec
=
info
->
pi_flags
.
sec
;
p
->
p_hdr
.
info
.
pi_flags
.
exp
=
info
->
pi_flags
.
exp
;
p
->
p_hdr
.
info
.
pi_lft
=
info
->
pi_lft
;
p
->
p_hdr
.
info
.
pi_streams
=
info
->
pi_streams
;
p
->
p_hdr
.
info
.
pi_port
=
info
->
pi_port
;
p
->
p_hdr
.
info
.
pi_tctimer
=
info
->
pi_tctimer
;
p
->
p_hdr
.
info
.
pi_twtimer
=
info
->
pi_twtimer
;
/* Move the items from one list to the other */
if
(
info
->
pi_endpoints
.
next
)
while
(
!
FD_IS_LIST_EMPTY
(
&
info
->
pi_endpoints
)
)
{
li
=
info
->
pi_endpoints
.
next
;
fd_list_unlink
(
li
);
fd_list_insert_before
(
&
p
->
p_hdr
.
info
.
pi_endpoints
,
li
);
}
/* The internal data */
if
(
orig_dbg
)
{
CHECK_MALLOC
(
p
->
p_dbgorig
=
strdup
(
orig_dbg
)
);
}
else
{
CHECK_MALLOC
(
p
->
p_dbgorig
=
strdup
(
"unknown"
)
);
}
p
->
p_cb
=
cb
;
p
->
p_cb_data
=
cb_data
;
/* Ok, now check if we don't already have an entry with the same Diameter Id, and insert this one */
CHECK_POSIX
(
pthread_rwlock_wrlock
(
&
fd_g_peers_rw
)
);
for
(
li
=
fd_g_peers
.
next
;
li
!=
&
fd_g_peers
;
li
=
li
->
next
)
{
struct
fd_peer
*
prev
=
(
struct
fd_peer
*
)
li
;
int
cmp
=
strcasecmp
(
p
->
p_hdr
.
info
.
pi_diamid
,
prev
->
p_hdr
.
info
.
pi_diamid
);
if
(
cmp
<
0
)
continue
;
if
(
cmp
==
0
)
ret
=
EEXIST
;
break
;
}
/* We can insert the new peer object */
if
(
!
ret
)
{
/* Update expiry list */
CHECK_FCT_DO
(
ret
=
fd_p_expi_update
(
p
),
goto
out
);
/* Insert the new element in the list */
fd_list_insert_before
(
li
,
&
p
->
p_hdr
.
chain
);
}
out:
CHECK_POSIX
(
pthread_rwlock_unlock
(
&
fd_g_peers_rw
)
);
if
(
ret
)
{
CHECK_FCT
(
fd_peer_free
(
&
p
)
);
}
else
{
CHECK_FCT
(
fd_psm_begin
(
p
)
);
}
return
ret
;
}
#define free_null( _v ) \
if (_v) { \
free(_v); \
...
...
@@ -139,7 +169,7 @@ static int fd_sp_reinit(struct fd_peer ** ptr)
}
/* Destroy a structure once all cleanups have been performed */
static
int
fd_sp_destroy
(
struct
fd_peer
**
ptr
)
int
fd_peer_free
(
struct
fd_peer
**
ptr
)
{
struct
fd_peer
*
p
;
void
*
t
;
...
...
@@ -209,85 +239,133 @@ static int fd_sp_destroy(struct fd_peer ** ptr)
return
0
;
}
/* Add a new peer entry */
int
fd_peer_add
(
struct
peer_info
*
info
,
char
*
orig_dbg
,
void
(
*
cb
)(
struct
peer_info
*
,
void
*
),
void
*
cb_data
)
/* Terminate peer module (destroy all peers) */
int
fd_peer_fini
()
{
struct
fd_peer
*
p
=
NULL
;
struct
fd_list
*
li
;
int
ret
=
0
;
TRACE_ENTRY
(
"%p %p %p %p"
,
info
,
orig_dbg
,
cb
,
cb_data
)
;
CHECK_PARAMS
(
info
&&
info
->
pi_diamid
)
;
struct
fd_list
purge
=
FD_LIST_INITIALIZER
(
purge
);
/* Store zombie peers here */
int
list_empty
;
struct
timespec
wait_until
,
now
;
/* Create a structure to contain the new peer information */
CHECK_FCT
(
fd_sp_reinit
(
&
p
)
);
/* Copy the informations from the parameters received */
CHECK_MALLOC
(
p
->
p_hdr
.
info
.
pi_diamid
=
strdup
(
info
->
pi_diamid
)
);
if
(
info
->
pi_realm
)
{
CHECK_MALLOC
(
p
->
p_hdr
.
info
.
pi_realm
=
strdup
(
info
->
pi_realm
)
);
}
TRACE_ENTRY
();
p
->
p_hdr
.
info
.
pi_flags
.
pro3
=
info
->
pi_flags
.
pro3
;
p
->
p_hdr
.
info
.
pi_flags
.
pro4
=
info
->
pi_flags
.
pro4
;
p
->
p_hdr
.
info
.
pi_flags
.
alg
=
info
->
pi_flags
.
alg
;
p
->
p_hdr
.
info
.
pi_flags
.
sec
=
info
->
pi_flags
.
sec
;
p
->
p_hdr
.
info
.
pi_flags
.
exp
=
info
->
pi_flags
.
exp
;
CHECK_FCT_DO
(
fd_p_expi_fini
(),
/* continue */
);
p
->
p_hdr
.
info
.
pi_lft
=
info
->
pi_lft
;
p
->
p_hdr
.
info
.
pi_streams
=
info
->
pi_streams
;
p
->
p_hdr
.
info
.
pi_port
=
info
->
pi_port
;
p
->
p_hdr
.
info
.
pi_tctimer
=
info
->
pi_tctimer
;
p
->
p_hdr
.
info
.
pi_twtimer
=
info
->
pi_twtimer
;
TRACE_DEBUG
(
INFO
,
"Sending terminate signal to all peer connections"
);