00001
00054 #include <stdlib.h>
00055 #include <time.h>
00056 #include <unistd.h>
00057
00058 #include "diameter.h"
00059
00060 #include "timer.h"
00061 #include "peermanager.h"
00062
00063 #include "globals.h"
00064 #include "peerstatemachine.h"
00065
00066 peer_list_t *peer_list=0;
00067 gen_lock_t *peer_list_lock=0;
00069 extern dp_config *config;
00070 extern char *dp_states[];
00071 AAAMsgIdentifier *hopbyhop_id=0;
00072 AAAMsgIdentifier *endtoend_id=0;
00073 gen_lock_t *msg_id_lock;
00081 int peer_manager_init(dp_config *config)
00082 {
00083 int i;
00084 peer *p;
00085 LOG(L_DBG,"DBG:peer_manager_init(): Peer Manager initialization...\n");
00086 peer_list = shm_malloc(sizeof(peer_list_t));
00087 peer_list->head = 0;
00088 peer_list->tail = 0;
00089 peer_list_lock = lock_alloc();
00090 peer_list_lock = lock_init(peer_list_lock);
00091
00092 hopbyhop_id = shm_malloc(sizeof(AAAMsgIdentifier));
00093 endtoend_id = shm_malloc(sizeof(AAAMsgIdentifier));
00094 msg_id_lock = lock_alloc();
00095 msg_id_lock = lock_init(msg_id_lock);
00096
00097 srand((unsigned int)time(0));
00098 *hopbyhop_id = rand();
00099 *endtoend_id = (time(0)&0xFFF)<<20;
00100 *endtoend_id |= rand() & 0xFFFFF;
00101
00102 for(i=0;i<config->peers_cnt;i++){
00103 p = new_peer(config->peers[i].fqdn,config->peers[i].realm,config->peers[i].port);
00104 if (!p) continue;
00105 p->is_dynamic = 0;
00106 add_peer(p);
00107 }
00108
00109 add_timer(PEER_MANAGER_TIMER,0,&peer_timer,0);
00110
00111 return 1;
00112 }
00113
00117 void peer_manager_destroy()
00118 {
00119 peer *foo,*bar;
00120 lock_get(peer_list_lock);
00121 foo = peer_list->head;
00122 while(foo){
00123 if (foo->I_sock>0) close(foo->I_sock);
00124 if (foo->R_sock>0) close(foo->R_sock);
00125 bar = foo->next;
00126 free_peer(foo,1);
00127 foo = bar;
00128 }
00129
00130
00131 shm_free(hopbyhop_id);
00132 shm_free(endtoend_id);
00133 lock_destroy(msg_id_lock);
00134 lock_dealloc((void*)msg_id_lock);
00135
00136 shm_free(peer_list);
00137 lock_destroy(peer_list_lock);
00138 lock_dealloc((void*)peer_list_lock);
00139 LOG(L_DBG,"DBG:peer_manager_init(): ...Peer Manager destroyed\n");
00140 }
00141
00146 void log_peer_list(int level)
00147 {
00148
00149 peer *p;
00150 int i;
00151 LOG(level,"--- Peer List: ---\n");
00152 for(p = peer_list->head;p;p = p->next){
00153 LOG(level,ANSI_GREEN" S["ANSI_YELLOW"%s"ANSI_GREEN"] "ANSI_BLUE"%.*s:%d"ANSI_GREEN" D["ANSI_RED"%c"ANSI_GREEN"]\n",dp_states[p->state],p->fqdn.len,p->fqdn.s,p->port,p->is_dynamic?'X':' ');
00154 for(i=0;i<p->applications_cnt;i++)
00155 LOG(level,ANSI_YELLOW"\t [%d,%d]\n",p->applications[i].id,p->applications[i].vendor);
00156 }
00157 LOG(level,"------------------\n");
00158 }
00159
00164 void add_peer(peer *p)
00165 {
00166 if (!p) return;
00167 lock_get(peer_list_lock);
00168 p->next = 0;
00169 p->prev = peer_list->tail;
00170 if (!peer_list->head) peer_list->head = p;
00171 if (peer_list->tail) peer_list->tail->next = p;
00172 peer_list->tail = p;
00173 lock_release(peer_list_lock);
00174 }
00175
00180 void remove_peer(peer *p)
00181 {
00182 peer *i;
00183 if (!p) return;
00184 i = peer_list->head;
00185 while(i&&i!=p) i = i->next;
00186 if (i){
00187 if (i->prev) i->prev->next = i->next;
00188 else peer_list->head = i->next;
00189 if (i->next) i->next->prev = i->prev;
00190 else peer_list->tail = i->prev;
00191 }
00192 }
00193
00199 peer *get_peer_from_sock(int sock)
00200 {
00201 peer *i;
00202 lock_get(peer_list_lock);
00203
00204 i = peer_list->head;
00205 while(i&&i->I_sock!=sock&&i->R_sock!=sock) i = i->next;
00206 lock_release(peer_list_lock);
00207 return i;
00208 }
00209
00216 peer *get_peer_from_fqdn(str fqdn,str realm)
00217 {
00218 peer *i;
00219 lock_get(peer_list_lock);
00220 i = peer_list->head;
00221 while(i){
00222 if (fqdn.len == i->fqdn.len && strncasecmp(fqdn.s,i->fqdn.s,fqdn.len)==0)
00223 break;
00224 i = i->next;
00225 }
00226 lock_release(peer_list_lock);
00227 if (!i&&config->accept_unknown_peers){
00228 i = new_peer(fqdn,realm,3868);
00229 if (i){
00230 i->is_dynamic=1;
00231 touch_peer(i);
00232 add_peer(i);
00233 }
00234 }
00235 return i;
00236 }
00237
00243 peer *get_peer_by_fqdn(str *fqdn)
00244 {
00245 peer *i;
00246 lock_get(peer_list_lock);
00247 i = peer_list->head;
00248 while(i){
00249 if (fqdn->len == i->fqdn.len && strncasecmp(fqdn->s,i->fqdn.s,fqdn->len)==0)
00250 break;
00251 i = i->next;
00252 }
00253 lock_release(peer_list_lock);
00254 return i;
00255 }
00256
00264 void peer_timer(time_t now,void *ptr)
00265 {
00266 peer *p,*n;
00267 LOG(L_DBG,"DBG:peer_timer(): taking care of peers...\n");
00268 lock_get(peer_list_lock);
00269 p = peer_list->head;
00270 while(p){
00271 lock_get(p->lock);
00272 n = p->next;
00273 if (p->activity+config->tc<=now){
00274 LOG(L_INFO,"DBG:peer_timer(): Peer %.*s \tState %d \n",p->fqdn.len,p->fqdn.s,p->state);
00275 switch (p->state){
00276
00277 case Closed:
00278 if (p->is_dynamic && config->drop_unknown_peers){
00279 remove_peer(p);
00280 free_peer(p,1);
00281 break;
00282 }
00283 touch_peer(p);
00284 sm_process(p,Start,0,1,0);
00285 break;
00286
00287 case Wait_Conn_Ack:
00288 case Wait_I_CEA:
00289 case Closing:
00290 case Wait_Returns:
00291 touch_peer(p);
00292 sm_process(p,Timeout,0,1,0);
00293 break;
00294
00295 case I_Open:
00296 case R_Open:
00297 if (p->waitingDWA){
00298 p->waitingDWA = 0;
00299 if (p->state==I_Open) sm_process(p,I_Peer_Disc,0,1,p->I_sock);
00300 if (p->state==R_Open) sm_process(p,R_Peer_Disc,0,1,p->R_sock);
00301 } else {
00302 p->waitingDWA = 1;
00303 Snd_DWR(p);
00304 touch_peer(p);
00305 }
00306 break;
00307
00308
00309 default:
00310 LOG(L_ERR,"ERROR:peer_timer(): Peer %.*s inactive in state %d\n",
00311 p->fqdn.len,p->fqdn.s,p->state);
00312 }
00313 }
00314 lock_release(p->lock);
00315 p = n;
00316 }
00317 lock_release(peer_list_lock);
00318 log_peer_list(L_INFO);
00319 }
00320
00325 inline AAAMsgIdentifier next_hopbyhop()
00326 {
00327 AAAMsgIdentifier x;
00328 lock_get(msg_id_lock);
00329 *hopbyhop_id = (*hopbyhop_id)+1;
00330 x = *hopbyhop_id;
00331 lock_release(msg_id_lock);
00332 return x;
00333 }
00334
00339 inline AAAMsgIdentifier next_endtoend()
00340 {
00341 AAAMsgIdentifier x;
00342 lock_get(msg_id_lock);
00343 *endtoend_id = (*endtoend_id)+1;
00344 x = *endtoend_id;
00345 lock_release(msg_id_lock);
00346 return x;
00347 }