/* ----------------------------------------------------------------------------- * recreate.c * * iPDC - Phasor Data Concentrator * * Copyright (C) 2011-2012 Nitesh Pandit * Copyright (C) 2011-2012 Kedar V. Khandeparkar * * This program 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. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * 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 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * Authors: * Nitesh Pandit * Kedar V. Khandeparkar * * ----------------------------------------------------------------------------- */ #include #include #include #include #include #include #include "parser.h" #include "global.h" #include "connections.h" #include "recreate.h" #include "new_pmu_or_pdc.h" /* ------------------------------------------------------------------------------------ */ /* Functions defined in recreate.c */ /* ------------------------------------------------------------------------------------ */ /* 1. recreate_cfg_objects() */ /* 2. void init_cfgparser() */ /* 3. void recreate_Connection_Table() */ /* 4. void recreate_udp_connections(struct Lower_Layer_Details *t11) */ /* 5. void recreate_tcp_connections(struct Lower_Layer_Details *t12) */ /* ------------------------------------------------------------------------------------ */ /* ---------------------------------------------------------------------------- */ /* FUNCTION recreate_cfg_objects(): */ /* It re-creates Configuration Objects from file cfg.bin if the ./server */ /* program is stopped abruptly. It internally calls init_cfgparser() */ /* ---------------------------------------------------------------------------- */ void recreate_cfg_objects(){ /* ---------------------------------------------------------------- */ /* Initialize Global Mutex Variable from global.h */ /* ---------------------------------------------------------------- */ pthread_mutex_init(&mutex_file, NULL); pthread_mutex_init(&mutex_cfg, NULL); pthread_mutex_init(&mutex_status_change, NULL); pthread_mutex_init(&mutex_Lower_Layer_Details, NULL); pthread_mutex_init(&mutex_Upper_Layer_Details, NULL); CMDSYNC[0] = 0xaa; CMDSYNC[1] = 0x41; CMDSYNC[2] = '\0'; CMDCFGSEND[0] = 0x00; CMDCFGSEND[1] = 0x05; CMDCFGSEND[2] = '\0'; CMDDATASEND[0] = 0x00; CMDDATASEND[1] = 0x02; CMDDATASEND[2] = '\0'; CMDDATAOFF[0] = 0x00; CMDDATAOFF[1] = 0x01; CMDDATAOFF[2] = '\0'; DATASYNC[0] = 0xaa; DATASYNC[1] = 0x01; DATASYNC[2] = '\0'; CFGSYNC[0] = 0xaa; CFGSYNC[1] = 0x31; CFGSYNC[2] = '\0'; int yes =1; /* Create UDP socket for DB Server and bind to DBPORT */ if ((DB_sockfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) { perror("socket"); exit(1); } else { printf("DB Socket:Sucessfully created\n"); } if (setsockopt(DB_sockfd,SOL_SOCKET,SO_REUSEADDR,&yes,sizeof(int)) == -1) { perror("setsockopt"); exit(1); } bzero(&DB_Server_addr,sizeof(DB_Server_addr)); DB_Server_addr.sin_family = AF_INET; // host byte order DB_Server_addr.sin_port = htons(DBPORT); // short, network byte order DB_Server_addr.sin_addr.s_addr = inet_addr(dbserver_ip); // automatically fill with my IP memset(&(DB_Server_addr.sin_zero),'\0', 8); // zero the rest of the struct unsigned char *line; unsigned int framesize; int tempi; char *rline = NULL, *d1; ssize_t read; size_t len = 0; /* Create CFG Objects from cfg.bin*/ FILE *file = fopen (ipdcFilePath,"rb"); if(file != NULL) { tempi = 1; while(tempi < 7) //iPDCServer { read = getline(&rline, &len, file); tempi++; } if(read > 0) //LowerDevices { d1 = strtok (rline," "); d1 = strtok (NULL,"\n"); tempi = atoi(d1); while (tempi > 0) { read = getline(&rline, &len, file); tempi--; } } read = getline(&rline, &len, file); //UpperDevices if(read > 0) { d1 = strtok (rline," "); d1 = strtok (NULL,"\n"); tempi = atoi(d1); while (tempi > 0) { read = getline(&rline, &len, file); tempi--; } } read = getline(&rline, &len, file); //SourcesCFG if(read > 0) { d1 = strtok (rline," "); d1 = strtok (NULL,"\n"); tempi = atoi(d1); if (tempi > 0) { getline(&rline, &len, file); framesize = atoi(rline); line = malloc(framesize*sizeof(unsigned char)); fread(line, sizeof(unsigned char), framesize, file); init_cfgparser(line); free(line); tempi--; } } fclose (file); } else { printf("iPDC Setup File is missing, iPDC exit.\n"); exit(1); } } /* ---------------------------------------------------------------------------- */ /* FUNCTION init_cfgparser(): */ /* It is called by recreate_cfg_object() to read the file `cfg.bin` */ /* and create cfg objects in the memory */ /* ---------------------------------------------------------------------------- */ void init_cfgparser(unsigned char st[]){ unsigned char *s; unsigned int phn,ann,dgn,num_pmu; int i,j,dgchannels; struct cfg_frame *cfg; struct channel_names *cn; /******************** PARSING BEGINGS *******************/ cfg = malloc(sizeof(struct cfg_frame)); if(!cfg) { printf("Not enough memory for cfg\n"); } s = st; /* Memory Allocation Begins - Allocate memory to framesize */ cfg->framesize = malloc(3*sizeof(unsigned char)); if(!cfg->framesize) { printf("Not enough memory for cfg->framesize\n"); } // Allocate memory to idcode cfg->idcode = malloc(3*sizeof(unsigned char)); if(!cfg->idcode) { printf("Not enough memory for cfg->framesize\n"); } // Allocate memory to soc cfg->soc = malloc(5*sizeof(unsigned char)); if(!cfg->soc) { printf("Not enough memory for cfg->soc\n"); } // Allocate memory to fracsec cfg->fracsec = malloc(5*sizeof(unsigned char)); if(!cfg->fracsec) { printf("Not enough memory for cfg->fracsec\n"); } // Allocate memory to time_base cfg->time_base = malloc(5*sizeof(unsigned char)); if(!cfg->time_base) { printf("Not enough memory for cfg->time_base\n"); } // Allocate memory to num_pmu cfg->num_pmu = malloc(3*sizeof(unsigned char)); if(!cfg->num_pmu) { printf("Not enough memory for cfg->num_pmu\n"); } // Allocate memory to data_rate cfg->data_rate = malloc(3*sizeof(unsigned char)); if(!cfg->data_rate) { printf("Not enough memory for cfg->data_rate\n"); } // Skip the sync word s = s + 2; // Separate the FRAME SIZE copy_cbyc (cfg->framesize,(unsigned char *)s,2); cfg->framesize[2]='\0'; s = s + 2; //SEPARATE IDCODE copy_cbyc (cfg->idcode,(unsigned char *)s,2); cfg->idcode[2]='\0'; int id = to_intconvertor(cfg->idcode); printf("ID Code %d\n",id); s = s + 2; //SEPARATE SOC copy_cbyc (cfg->soc,(unsigned char *)s,4); cfg->soc[4]='\0'; s = s + 4; //SEPARATE FRACSEC copy_cbyc (cfg->fracsec,(unsigned char *)s,4); cfg->fracsec[4]='\0'; s = s + 4; //SEPARATE TIMEBASE copy_cbyc (cfg->time_base,(unsigned char *)s,4); cfg->time_base[4]='\0'; s = s + 4; //SEPARATE PMU NUM copy_cbyc (cfg->num_pmu,(unsigned char *)s,2); cfg->num_pmu[2]='\0'; s = s + 2; num_pmu = to_intconvertor(cfg->num_pmu); printf("Number of PMU's = %d.\n",num_pmu); // Allocate Memeory For Each PMU cfg->pmu = malloc(num_pmu* sizeof(struct for_each_pmu *)); if(!cfg->pmu) { printf("Not enough memory pmu[][]\n"); exit(1); } for (i = 0; i < num_pmu; i++) { cfg->pmu[i] = malloc(sizeof(struct for_each_pmu)); } j = 0; ///WHILE EACH PMU IS HANDLED while(jpmu[j]->stn = malloc(17*sizeof(unsigned char)); if(!cfg->pmu[j]->stn) { printf("Not enough memory cfg->pmu[j]->stn\n"); exit(1); } // Memory Allocation for idcode cfg->pmu[j]->idcode = malloc(3*sizeof(unsigned char)); if(!cfg->pmu[j]->idcode) { printf("Not enough memory cfg->pmu[j]->idcode\n"); exit(1); } // Memory Allocation for format cfg->pmu[j]->data_format = malloc(3*sizeof(unsigned char)); if(!cfg->pmu[j]->data_format) { printf("Not enough memory cfg->pmu[j]->data_format\n"); exit(1); } // Memory Allocation for phnmr cfg->pmu[j]->phnmr = malloc(3*sizeof(unsigned char)); if(!cfg->pmu[j]->phnmr) { printf("Not enough memory cfg->pmu[j]->phnmr\n"); exit(1); } // Memory Allocation for annmr cfg->pmu[j]->annmr = malloc(3*sizeof(unsigned char)); if(!cfg->pmu[j]->annmr) { printf("Not enough memory cfg->pmu[j]->annmr\n"); exit(1); } // Memory Allocation for dgnmr cfg->pmu[j]->dgnmr = malloc(3*sizeof(unsigned char)); if(!cfg->pmu[j]->dgnmr) { printf("Not enough memory cfg->pmu[j]->dgnmr\n"); exit(1); } // Memory Allocation for fnom cfg->pmu[j]->fnom = malloc(3*sizeof(unsigned char)); if(!cfg->pmu[j]->fnom) { printf("Not enough memory cfg->pmu[j]->fnom\n"); exit(1); } // Memory Allocation for cfg_cnt cfg->pmu[j]->cfg_cnt = malloc(3*sizeof(unsigned char)); if(!cfg->pmu[j]->cfg_cnt) { printf("Not enough memory cfg->pmu[j]->cfg_cnt\n"); exit(1); } //SEPARATE STATION NAME copy_cbyc (cfg->pmu[j]->stn,(unsigned char *)s,16); cfg->pmu[j]->stn[16]='\0'; s = s + 16; //SEPARATE IDCODE copy_cbyc (cfg->pmu[j]->idcode,(unsigned char *)s,2); cfg->pmu[j]->idcode[2]='\0'; s = s + 2; //SEPARATE DATA FORMAT copy_cbyc (cfg->pmu[j]->data_format,(unsigned char *)s,2); cfg->pmu[j]->data_format[2]='\0'; s = s + 2; // USE fmt unsigned char hex = cfg->pmu[j]->data_format[1]; hex <<= 4; // Extra field has been added to identify polar,rectangular,floating/fixed point cfg->pmu[j]->fmt = malloc(sizeof(struct format)); if((hex & 0x80) == 0x80) cfg->pmu[j]->fmt->freq = '1'; else cfg->pmu[j]->fmt->freq = '0'; if((hex & 0x40) == 0x40 ) cfg->pmu[j]->fmt->analog = '1'; else cfg->pmu[j]->fmt->analog = '0'; if((hex & 0x20) == 0x20) cfg->pmu[j]->fmt->phasor = '1'; else cfg->pmu[j]->fmt->phasor = '0'; if((hex & 0x10) == 0x10) cfg->pmu[j]->fmt->polar = '1'; else cfg->pmu[j]->fmt->polar = '0'; //SEPARATE PHASORS copy_cbyc (cfg->pmu[j]->phnmr,(unsigned char *)s,2); cfg->pmu[j]->phnmr[2]='\0'; s = s + 2; phn = to_intconvertor(cfg->pmu[j]->phnmr); //SEPARATE ANALOGS copy_cbyc (cfg->pmu[j]->annmr,(unsigned char *)s,2); cfg->pmu[j]->annmr[2]='\0'; s = s + 2; ann = to_intconvertor(cfg->pmu[j]->annmr); //SEPARATE DIGITALS copy_cbyc (cfg->pmu[j]->dgnmr,(unsigned char *)s,2); cfg->pmu[j]->dgnmr[2] = '\0'; s = s + 2; dgn = to_intconvertor(cfg->pmu[j]->dgnmr); printf("CFG consist Phasor = %d, Analogs = %d, and Digitals = %d.\n",phn,ann,dgn); cn = malloc(sizeof(struct channel_names)); if(!cn) { printf("Not enough memory cn\n"); exit(1); } cn->first = NULL; ////SEPARATE PHASOR NAMES if(phn != 0){ cn->phnames = malloc(phn*sizeof(unsigned char*)); if(!cn->phnames) { printf("Not enough memory cfg->pmu[j]->cn->phnames[][]\n"); exit(1); } for (i = 0; i < phn; i++) { cn->phnames[i] = malloc(17*sizeof(unsigned char)); } i = 0;//Index for PHNAMES while(iphnames[i],(unsigned char *)s,16); cn->phnames[i][16] = '\0'; printf("Phnames %s\n",cn->phnames[i]); s = s + 16; i++; } } //SEPARATE ANALOG NAMES if(ann!=0){ cn->angnames = malloc(ann*sizeof(unsigned char*)); if(!cn->angnames) { printf("Not enough memory cfg->pmu[j]->cn->phnames[][]\n"); exit(1); } for (i = 0; i < ann; i++) { cn->angnames[i] = malloc(17*sizeof(unsigned char)); } i=0;//Index for ANGNAMES while(iangnames[i],(unsigned char *)s,16); cn->angnames[i][16]='\0'; printf("ANGNAMES %s\n",cn->angnames[i]); s =s + 16; i++; } } i = 0; //Index for number of dgwords struct dgnames *q; while(idgn = malloc(16*sizeof(unsigned char *)); if(!temp1->dgn) { printf("Not enough memory temp1->dgn\n"); exit(1); } for (i = 0; i < 16; i++) { temp1->dgn[i] = malloc(17*sizeof(unsigned char)); } temp1->dg_next = NULL; for(dgchannels=0;dgchannels<16;dgchannels++){ copy_cbyc (temp1->dgn[dgchannels],(unsigned char *)s,16); temp1->dgn[dgchannels][16]='\0'; s += 16; printf("%s\n",temp1->dgn[dgchannels]); } if(cn->first == NULL){ cn->first = q = temp1; } else { while(q->dg_next!=NULL){ q = q->dg_next; } q->dg_next = temp1; } i++; } //DGWORD WHILE ENDS cfg->pmu[j]->cnext = cn;//Assign to pointers ///PHASOR FACTORS if(phn != 0){ cfg->pmu[j]->phunit = malloc(phn*sizeof(unsigned char*)); if(!cfg->pmu[j]->phunit) { printf("Not enough memory cfg->pmu[j]->phunit[][]\n"); exit(1); } for (i = 0; i < phn; i++) { cfg->pmu[j]->phunit[i] = malloc(5*sizeof(unsigned char)); } i = 0; while(ipmu[j]->phunit[i],(unsigned char *)s,4); cfg->pmu[j]->phunit[i][4] = '\0'; s = s + 4; i++; } }//if for PHASOR Factors ends //ANALOG FACTORS if(ann != 0){ cfg->pmu[j]->anunit = malloc(ann*sizeof(unsigned char*)); if(!cfg->pmu[j]->anunit) { printf("Not enough memory cfg->pmu[j]->anunit[][]\n"); exit(1); } for (i = 0; i < ann; i++) { cfg->pmu[j]->anunit[i] = malloc(5*sizeof(unsigned char)); } i = 0; while(ipmu[j]->anunit[i],(unsigned char *)s,4); cfg->pmu[j]->anunit[i][4] = '\0'; s = s + 4; i++; } } // if for ANALOG Factors ends if(dgn != 0){ cfg->pmu[j]->dgunit = malloc(dgn*sizeof(unsigned char*)); if(!cfg->pmu[j]->dgunit) { printf("Not enough memory cfg->pmu[j]->dgunit[][]\n"); exit(1); } for (i = 0; i < dgn; i++) { cfg->pmu[j]->dgunit[i] = malloc(5*sizeof(unsigned char)); } i = 0; while(ipmu[j]->dgunit[i],(unsigned char *)s,4); cfg->pmu[j]->dgunit[i][4] = '\0'; s = s + 4; i++; } } //if for Digital Words Factors ends copy_cbyc (cfg->pmu[j]->fnom,(unsigned char *)s,2); cfg->pmu[j]->fnom[2]='\0'; s = s + 2; copy_cbyc (cfg->pmu[j]->cfg_cnt,(unsigned char *)s,2); cfg->pmu[j]->cfg_cnt[2] = '\0'; s = s + 2; j++; }//While for PMU number ends copy_cbyc (cfg->data_rate,(unsigned char *)s,2); cfg->data_rate[2] = '\0'; cfg->cfgnext = NULL; if (cfgfirst == NULL) { cfgfirst = cfg; } else { struct cfg_frame *t=cfgfirst; while(t->cfgnext != NULL){ t = t->cfgnext; } t->cfgnext = cfg; } } /* ---------------------------------------------------------------------------- */ /* FUNCTION recreate_Connection_Table(): */ /* It re-creates objects by reading the file ipdcINFO.bin.*/ /* ---------------------------------------------------------------------------- */ void recreate_Connection_Table() { char line[40],*ip,*port,*protocol,*id; char *rline = NULL, *d1; int err, tempi; FILE *f; ssize_t read; size_t len = 0; // A new thread is created for each TCP connection in 'detached' mode. Thus allowing any number of threads to be created. pthread_attr_t attr; pthread_attr_init(&attr); /* In the detached state, the thread resources are immediately freed when it terminates, but pthread_join(3) cannot be used to synchronize on the thread termination. */ if((err = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED))) { perror(strerror(err)); exit(1); } /* Shed policy = SCHED_FIFO (realtime, first-in first-out) */ if((err = pthread_attr_setschedpolicy(&attr,SCHED_FIFO))) { perror(strerror(err)); exit(1); } f = fopen(ipdcFilePath,"rb"); tempi = 1; while(tempi < 7) { read = getline(&rline, &len, f); tempi++; } if(read > 0) { d1 = strtok (rline," "); d1 = strtok (NULL,"\n"); tempi = atoi(d1); if (tempi > 0) //1 if { printf("#### CONNECTION TABLE OF SOURCE DEVICES ####\n"); printf("-----------------------------------------------------------------\n"); printf("| PMU ID | Lower IP | Port | Protocol |\n"); printf("-----------------------------------------------------------------\n"); while (tempi > 0) //2 while { read = getline(&rline, &len, f); /* Extract the ip and protocol */ id = strtok (rline,","); ip = strtok (NULL,","); port = strtok (NULL,","); protocol = strtok (NULL,"\n"); protocol[3] = '\0'; printf("|\t%d\t|%s\t|\t%d\t|\t%s\t|\n",atoi(id),ip,atoi(port),protocol); struct Lower_Layer_Details *temp_pmu; temp_pmu = malloc(sizeof(struct Lower_Layer_Details)); if(!temp_pmu) { printf("Not enough memory temp_pmu\n"); exit(1); } temp_pmu->pmuid = atoi(id); strcpy(temp_pmu->ip,ip); temp_pmu->port = atoi(port); strcpy(temp_pmu->protocol,protocol); temp_pmu->data_transmission_off = 0; temp_pmu->pmu_remove = 0; temp_pmu->request_cfg_frame = 0; temp_pmu->next = NULL; temp_pmu->prev = NULL; if(!strncasecmp(temp_pmu->protocol,"UDP",3)) { recreate_udp_connections(temp_pmu); } if(!strncasecmp(temp_pmu->protocol,"TCP",3)) { recreate_tcp_connections(temp_pmu); } memset(line,'\0',40); tempi--; } printf("-----------------------------------------------------------------\n"); } else { printf("Source Devices Not Found.\n"); } } read = getline(&rline, &len, f); if(read > 0) { d1 = strtok (rline," "); d1 = strtok (NULL,"\n"); tempi = atoi(d1); if (tempi > 0) //1 if { printf("#### CONNECTION TABLE OF DESTINATION DEVICES ####\n"); printf("-------------------------------------------------\n"); printf("| Upper IP | Port | Protocol |\n"); printf("-------------------------------------------------\n"); while (tempi > 0) //2 while { read = getline(&rline, &len, f); /* Extract the ip and protocol */ ip = strtok (rline,","); port = strtok (NULL,","); protocol = strtok (NULL,"\n"); protocol[3] = '\0'; printf("|%s\t|\t%d\t|\t%s\t|\n",ip,atoi(port),protocol); struct Upper_Layer_Details *temp_pdc; temp_pdc = malloc(sizeof(struct Upper_Layer_Details)); if(!temp_pdc) { printf("Not enough memory temp_pmu\n"); exit(1); } strcpy(temp_pdc->ip,ip); temp_pdc->port = atoi(port); strcpy(temp_pdc->protocol,protocol); bzero(&temp_pdc->pdc_addr,sizeof(temp_pdc->pdc_addr)); temp_pdc->pdc_addr.sin_family = AF_INET; temp_pdc->pdc_addr.sin_addr.s_addr = inet_addr(temp_pdc->ip); temp_pdc->pdc_addr.sin_port = htons(temp_pdc->port); memset(&(temp_pdc->pdc_addr.sin_zero), '\0', 8); // zero the rest of the struct temp_pdc->config_change = 0; temp_pdc->UL_upper_pdc_cfgsent = 0; temp_pdc->UL_data_transmission_off = 1; temp_pdc->address_set = 0; temp_pdc->tcpup = 1; if(ULfirst == NULL) { ULfirst = temp_pdc; temp_pdc->prev = NULL; } else { ULlast->next = temp_pdc; temp_pdc->prev = ULlast; } ULlast = temp_pdc; temp_pdc->next = NULL; memset(line,'\0',40); tempi--; } printf("-------------------------------------------------\n"); } else { printf("Destination Devices Not Found.\n"); } } fclose(f); } /* ---------------------------------------------------------------------------- */ /* FUNCTION recreate_udp_connections(struct Lower_Layer_Details *t11): */ /* ---------------------------------------------------------------------------- */ void recreate_udp_connections(struct Lower_Layer_Details *t11) { int err; pthread_attr_t attr; pthread_attr_init(&attr); /* In the detached state, the thread resources are immediately freed when it terminates, but pthread_join(3) cannot be used to synchronize on the thread termination. */ if((err = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED))) { perror(strerror(err)); exit(1); } /* Shed policy = SCHED_FIFO (realtime, first-in first-out) */ if((err = pthread_attr_setschedpolicy(&attr,SCHED_FIFO))) { perror(strerror(err)); exit(1); } pthread_t t; if(pthread_create(&t,&attr,connect_pmu_udp,(void *)t11)) { perror(strerror(err)); exit(1); } } /* ---------------------------------------------------------------------------- */ /* FUNCTION recreate_tcp_connections(struct Lower_Layer_Details *t12): */ /* ---------------------------------------------------------------------------- */ void recreate_tcp_connections(struct Lower_Layer_Details *t12) { int err; pthread_attr_t attr; pthread_attr_init(&attr); /* In the detached state, the thread resources are immediately freed when it terminates, but pthread_join(3) cannot be used to synchronize on the thread termination. */ if((err = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED))) { perror(strerror(err)); exit(1); } /* Shed policy = SCHED_FIFO (realtime, first-in first-out) */ if((err = pthread_attr_setschedpolicy(&attr,SCHED_FIFO))) { perror(strerror(err)); exit(1); } pthread_t t; if(pthread_create(&t,&attr,connect_pmu_tcp,(void *)t12)) { perror(strerror(err)); exit(1); } } /**************************************** End of File *******************************************************/