00001
00055 #include <stdlib.h>
00056 #include <sys/wait.h>
00057 #include <signal.h>
00058 #include <stdio.h>
00059
00060 #include "utils.h"
00061 #include "diameter_peer.h"
00062
00063 #include "config.h"
00064 #include "acceptor.h"
00065 #include "timer.h"
00066 #include "peermanager.h"
00067 #include "worker.h"
00068 #include "api_process.h"
00069 #include "transaction.h"
00070 #include "session.h"
00071
00072 #ifdef CDP_FOR_SER
00073 #include "../../pt.h"
00074 #endif
00075
00076 dp_config *config=0;
00078 int *shutdownx=0;
00079 gen_lock_t *shutdownx_lock;
00081 pid_t *dp_first_pid;
00083 pid_list_head_t *pid_list;
00084 gen_lock_t *pid_list_lock;
00086 extern handler_list *handlers;
00087 extern gen_lock_t *handlers_lock;
00095 inline int dp_add_pid(pid_t pid)
00096 {
00097 pid_list_t *n;
00098 lock_get(pid_list_lock);
00099 n = shm_malloc(sizeof(pid_list_t));
00100 if (!n){
00101 LOG_NO_MEM("shm",sizeof(pid_list_t));
00102 lock_release(pid_list_lock);
00103 return 0;
00104 }
00105 n->pid = pid;
00106 n->next = 0;
00107 n->prev = pid_list->tail;
00108 if (!pid_list->head) pid_list->head = n;
00109 if (pid_list->tail) pid_list->tail->next = n;
00110 pid_list->tail = n;
00111 lock_release(pid_list_lock);
00112 return 1;
00113 }
00114
00118 inline int dp_last_pid()
00119 {
00120 int pid;
00121 lock_get(pid_list_lock);
00122 if (pid_list->tail) pid = pid_list->tail->pid;
00123 else pid = -1;
00124 lock_release(pid_list_lock);
00125 return pid;
00126 }
00127
00132 inline void dp_del_pid(pid_t pid)
00133 {
00134 pid_list_t *i;
00135 lock_get(pid_list_lock);
00136 i = pid_list->head;
00137 if (!i) {
00138 lock_release(pid_list_lock);
00139 return;
00140 }
00141 while(i && i->pid!=pid) i = i->next;
00142 if (i){
00143 if (i->prev) i->prev->next = i->next;
00144 else pid_list->head = i->next;
00145 if (i->next) i->next->prev = i->prev;
00146 else pid_list->tail = i->prev;
00147 shm_free(i);
00148 }
00149 lock_release(pid_list_lock);
00150 }
00151
00152
00159 int diameter_peer_init(char *cfg_filename)
00160 {
00161 pid_list_t *i,*j;
00162
00163 config = parse_dp_config(cfg_filename);
00164 if (!config) {
00165 LOG(L_ERR,"ERROR:init_diameter_peer(): Error loading configuration file. Aborting...\n");
00166 goto error;
00167 }
00168 log_dp_config(L_INFO,config);
00169
00170 dp_first_pid = shm_malloc(sizeof(pid_t));
00171 if (!dp_first_pid){
00172 LOG_NO_MEM("shm",sizeof(pid_t));
00173 goto error;
00174 }
00175 *dp_first_pid = getpid();
00176
00177 shutdownx = shm_malloc(sizeof(int));
00178 if (!shutdownx){
00179 LOG_NO_MEM("shm",sizeof(int));
00180 goto error;
00181 }
00182 *shutdownx = 0;
00183
00184 shutdownx_lock = lock_alloc();
00185 if (!shutdownx_lock){
00186 LOG_NO_MEM("shm",sizeof(gen_lock_t));
00187 goto error;
00188 }
00189 shutdownx_lock = lock_init(shutdownx_lock);
00190
00191 handlers_lock = lock_alloc();
00192 if (!handlers_lock){
00193 LOG_NO_MEM("shm",sizeof(gen_lock_t));
00194 goto error;
00195 }
00196 handlers_lock = lock_init(handlers_lock);
00197
00198 handlers = shm_malloc(sizeof(handler_list));
00199 if (!handlers){
00200 LOG_NO_MEM("shm",sizeof(handler_list));
00201 goto error;
00202 }
00203 handlers->head=0;
00204 handlers->tail=0;
00205
00206
00207 pid_list = shm_malloc(sizeof(pid_list_head_t));
00208 pid_list_lock = lock_alloc();
00209 pid_list_lock = lock_init(pid_list_lock);
00210
00211
00212 timer_cdp_init();
00213 worker_init();
00214
00215
00216 peer_manager_init(config);
00217
00218
00219 if (!session_init()) goto error;
00220
00221 #ifdef CDP_FOR_SER
00222
00223 trans_init();
00224
00225
00226 cb_add(api_callback,0);
00227
00228 #endif
00229
00230 return 1;
00231
00232 error:
00233 if (shutdownx) shm_free(shutdownx);
00234 if (config) free_dp_config(config);
00235 i = pid_list->head;
00236 while(i){
00237 j = i->next;
00238 shm_free(i);
00239 i = j;
00240 }
00241 shm_free(pid_list);
00242 lock_get(pid_list_lock);
00243 lock_destroy(pid_list_lock);
00244 lock_dealloc((void*)pid_list_lock);
00245 return 0;
00246
00247 }
00248
00249
00257 int diameter_peer_start(int blocking)
00258 {
00259 int pid;
00260 int k=0;
00261
00262
00263
00264 #ifdef CDP_FOR_SER
00265 pid = fork_process(1000,"cdp_acceptor",1);
00266 #else
00267 pid = fork();
00268 #endif
00269 if (pid==-1){
00270 LOG(L_CRIT,"ERROR:init_diameter_peer(): Error on fork() for acceptor!\n");
00271 return 0;
00272 }
00273 if (pid==0) {
00274 acceptor_process(config);
00275 LOG(L_CRIT,"ERROR:init_diameter_peer(): acceptor_process finished without exit!\n");
00276 exit(-1);
00277 }else{
00278 dp_add_pid(pid);
00279 }
00280
00281
00282 for(k=0;k<config->workers;k++){
00283 #ifdef CDP_FOR_SER
00284 pid = fork_process(1001+k,"cdp_worker",1);
00285 #else
00286 pid = fork();
00287 #endif
00288 if (pid==-1){
00289 LOG(L_CRIT,"ERROR:init_diameter_peer(): Error on fork() for worker!\n");
00290 return 0;
00291 }
00292 if (pid==0) {
00293 srandom(time(0)*k);
00294 #ifdef CDP_FOR_SER
00295 snprintf(pt[process_no].desc, MAX_PT_DESC,
00296 "cdp worker child=%d", k );
00297 #endif
00298 worker_process(k);
00299 LOG(L_CRIT,"ERROR:init_diameter_peer(): worker_process finished without exit!\n");
00300 exit(-1);
00301 }else{
00302 dp_add_pid(pid);
00303 }
00304 }
00305
00306
00307 if (blocking) {
00308 dp_add_pid(getpid());
00309 timer_process(1);
00310 }
00311 else{
00312 #ifdef CDP_FOR_SER
00313 pid = fork_process(1001,"cdp_timer",1);
00314 #else
00315 pid = fork();
00316 #endif
00317 if (pid==-1){
00318 LOG(L_CRIT,"ERROR:init_diameter_peer(): Error on fork() for timer!\n");
00319 return 0;
00320 }
00321 if (pid==0) {
00322 timer_process(0);
00323 LOG(L_CRIT,"ERROR:init_diameter_peer(): timer_process finished without exit!\n");
00324 exit(-1);
00325 }else{
00326 dp_add_pid(pid);
00327 }
00328 }
00329
00330 return 1;
00331 }
00332
00333 extern int memlog;
00334
00339 void diameter_peer_destroy()
00340 {
00341 int pid,status;
00342 handler *h;
00343
00344 lock_get(shutdownx_lock);
00345 if (*shutdownx) {
00346
00347 lock_release(shutdownx_lock);
00348 return;
00349 }else {
00350
00351 *shutdownx = 1;
00352 lock_release(shutdownx_lock);
00353 }
00354
00355
00356 worker_poison_queue();
00357
00358
00359 LOG(L_INFO,"INFO:destroy_diameter_peer(): Terminating all childs...\n");
00360 while(pid_list->tail){
00361 pid = dp_last_pid();
00362 if (pid<=0||pid==getpid()){
00363 dp_del_pid(pid);
00364 continue;
00365 }
00366 LOG(L_INFO,"INFO:destroy_diameter_peer(): Waiting for child [%d] to terminate...\n",pid);
00367 if (waitpid(pid,&status,0)<0){
00368 dp_del_pid(pid);
00369 continue;
00370 }
00371 if (!WIFEXITED(status) ){
00372 worker_poison_queue();
00373 sleep(1);
00374 } else {
00375 dp_del_pid(pid);
00376 }
00377
00378 }
00379 LOG(L_INFO,"INFO:destroy_diameter_peer(): All processes terminated. Cleaning up.\n");
00380
00381
00382 timer_cdp_destroy();
00383
00384
00385 worker_destroy();
00386
00387
00388 peer_manager_destroy();
00389
00390
00391 session_destroy();
00392
00393
00394
00395 shm_free(dp_first_pid);
00396 shm_free(pid_list);
00397 lock_destroy(pid_list_lock);
00398 lock_dealloc((void*)pid_list_lock);
00399
00400 shm_free(shutdownx);
00401
00402 lock_destroy(shutdownx_lock);
00403 lock_dealloc((void*)shutdownx_lock);
00404
00405 lock_get(handlers_lock);
00406 while(handlers->head){
00407 h = handlers->head->next;
00408 shm_free(handlers->head);
00409 handlers->head = h;
00410 }
00411 lock_destroy(handlers_lock);
00412 lock_dealloc((void*)handlers_lock);
00413 shm_free(handlers);
00414
00415 free_dp_config(config);
00416 LOG(L_CRIT,"INFO:destroy_diameter_peer(): Bye Bye from C Diameter Peer test\n");
00417
00418 #ifndef CDP_FOR_SER
00419 #ifdef PKG_MALLOC
00420 LOG(memlog, "Memory status (pkg):\n");
00421
00422 #ifdef pkg_sums
00423 pkg_sums();
00424 #endif
00425 #endif
00426 #ifdef SHM_MEM
00427 LOG(memlog, "Memory status (shm):\n");
00428
00429 #ifdef shm_sums
00430 shm_sums();
00431 #endif
00432
00433 shm_mem_destroy();
00434 #endif
00435 #endif
00436 }
00437
00438