peermanager.c

Go to the documentation of this file.
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 /*  lock_get(msg_id_lock);  */
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     /* must have lock on peer_list_lock when calling this!!! */
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                 /* initiating connection */
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                 /* timeouts */  
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                 /* inactivity detected */
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                 /* ignored states */    
00308                 /* unknown states */
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 }

Generated on Tue Jul 29 04:19:11 2008 for Open IMS Core CSCFs by  doxygen 1.5.2