/* ----------------------------------------------------------------------------- * new_pmu_or_pdc.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 * * ----------------------------------------------------------------------------- */ /* ---------------------------------------------------------------------------------------------*/ /* Functions defined in new_pmu_or_pdc.c */ /* ---------------------------------------------------------------------------------------------*/ /* 1. int add_PMU(char pmuid[], char ip[], char port[], char protocol[]) */ /* 2. void* connect_pmu_tcp(void *temp) */ /* 3. void* connect_pmu_udp(void *temp) */ /* 4. void add_PMU_Node(struct Lower_Layer_Details *temp_pmu) */ /* 5. int remove_Lower_Node(char pmuid[], char protocol[]) */ /* 6. void* remove_llnode(void*) */ /* 7. int put_data_transmission_off(char pmuid[], char protocol[]) */ /* 8. void* data_off_llnode(void* temp) */ /* 9. int put_data_transmission_on(char pmuid[], char protocol[]) */ /* 10. void* data_on_llnode(void* temp) */ /* 11. int configuration_request(char pmuid[], char protocol[]) */ /* 12. void* config_request(void* temp) */ /* 13. int add_PDC(char ip[], char protocol[]) */ /* 14. int remove_PDC(char ip[], char port_num[], char protocol[]) */ /* 15. void display_CT() */ /* 16. void create_command_frame(int type,int pmuid,char *) */ /* 17. int checkip(char ip[]) */ /* ---------------------------------------------------------------------------------------------*/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "ipdcGui.h" #include "connections.h" #include "parser.h" #include "global.h" #include "new_pmu_or_pdc.h" #include "dallocate.h" /* ---------------------------------------------------------------------------- */ /* FUNCTION add_PMU(): */ /* It Makes an entry in iPDC Setup File for each new Lower layer PMU/PDC. */ /* A node is created of the type Lower_Layer_Details. A separate thread is */ /* created for each added lower layer PMU/PDC accoring to the protcol (TCP/UDP).*/ /* ---------------------------------------------------------------------------- */ int add_PMU(char pmuid[], char ip[], char port[], char protocol[]) { int err; int flag = 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); } if(LLfirst != NULL) { struct Lower_Layer_Details *temp_ptr; temp_ptr = malloc(sizeof(struct Lower_Layer_Details)); if(!temp_ptr) { printf("Not enough memory temp_pmu\n"); exit(1); } temp_ptr = LLfirst; while (temp_ptr != NULL) { if(temp_ptr->pmuid == atoi(pmuid)) { flag = 1; break; } else { temp_ptr = temp_ptr->next; continue; } } } if(flag) /* 2 if there is a match */ { printf("%s %s is already in the LowerDevices list Enter another PMU\n",pmuid,protocol); return 1; } else if(!flag) { /* Make a node that contains PMU IP, Port and Protocol details */ 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(pmuid); // PMUID strcpy(temp_pmu->ip,ip); // ip temp_pmu->port = atoi(port); // port strcpy(temp_pmu->protocol,protocol); // protocol temp_pmu->protocol[3] = '\0'; temp_pmu->up = 1; 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; pthread_t t; if(!strncasecmp(protocol,"UDP",3)) { if((err = pthread_create(&t,&attr,connect_pmu_udp,(void *)temp_pmu))) { perror(strerror(err)); exit(1); } } else if(!strncasecmp(protocol,"TCP",3)) { if((err = pthread_create(&t,&attr,connect_pmu_tcp,(void *)temp_pmu))) { perror(strerror(err)); exit(1); } } struct Upper_Layer_Details *temp_pdc = ULfirst; pthread_mutex_lock(&mutex_Upper_Layer_Details); while(temp_pdc != NULL ) { temp_pdc->config_change = 1; temp_pdc = temp_pdc->next; } pthread_mutex_unlock(&mutex_Upper_Layer_Details); return 0; } // If no match return 1; } /* ---------------------------------------------------------------------------- */ /* FUNCTION connect_pmu_tcp(): */ /* It Makes a new tcp connections with each added Lower Layer PMU/PDC. */ /* ---------------------------------------------------------------------------- */ void* connect_pmu_tcp(void *temp) { int tcp_sockfd,port_num,yes = 1; struct sockaddr_in PMU_addr; struct Lower_Layer_Details *temp_pmu = (struct Lower_Layer_Details *) temp; unsigned char *tcp_BUF,*ptr,length[2]; unsigned int flen; uint16_t cal_crc,frame_crc; port_num = temp_pmu->port; if ((tcp_sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) { perror("socket"); exit(1); } if (setsockopt(tcp_sockfd,SOL_SOCKET,SO_REUSEADDR,&yes,sizeof(int)) == -1) { perror("setsockopt"); exit(1); } bzero(&PMU_addr,sizeof(PMU_addr)); PMU_addr.sin_family = AF_INET; PMU_addr.sin_addr.s_addr = inet_addr(temp_pmu->ip); PMU_addr.sin_port = htons(port_num); memset(&(PMU_addr.sin_zero), '\0', 8); // zero the rest of the struct /* Copy the information of Lower Layer PMU/PDC to the node */ temp_pmu->thread_id = pthread_self(); bzero(&temp_pmu->llpmu_addr,sizeof(PMU_addr)); temp_pmu->llpmu_addr.sin_family = AF_INET; temp_pmu->llpmu_addr.sin_addr.s_addr = inet_addr(temp_pmu->ip); temp_pmu->llpmu_addr.sin_port = htons(port_num); memset(&(temp_pmu->llpmu_addr.sin_zero), '\0', 8); // zero the rest of the struct temp_pmu->sockfd = tcp_sockfd; temp_pmu->up = 1; if (connect(tcp_sockfd, (struct sockaddr *)&PMU_addr, sizeof(PMU_addr)) == -1) { // Main if perror("connect"); temp_pmu->up = 0; add_PMU_Node(temp_pmu); pthread_exit(NULL); } else { /* Add PMU*/ add_PMU_Node(temp_pmu); tcp_BUF = malloc(MAXBUFLEN* sizeof(unsigned char)); /* Sending Command for obtaining CFG */ int n,bytes_read; char *cmdframe = malloc(19); cmdframe[18] = '\0'; create_command_frame(1,temp_pmu->pmuid,cmdframe); if ((n = send (tcp_sockfd,cmdframe,18,0) == -1)) { perror("send"); } else { free(cmdframe); while(1) { memset(tcp_BUF, '\0', MAXBUFLEN * sizeof(unsigned char)); bytes_read = recv (tcp_sockfd, tcp_BUF,MAXBUFLEN-1,0); if(bytes_read == 0) { /* When TCP Peer Terminates */ printf("No data received Closing tcp socket %d\n",tcp_sockfd); temp_pmu->up = 0; struct Upper_Layer_Details *temp_pdc = ULfirst; pthread_mutex_lock(&mutex_Upper_Layer_Details); while(temp_pdc != NULL ) { temp_pdc->config_change = 1; temp_pdc = temp_pdc->next; } pthread_mutex_unlock(&mutex_Upper_Layer_Details); pthread_exit(NULL); } else if(bytes_read == -1) {/* When TCP Peer Terminates */ perror("recv"); temp_pmu->up = 0; struct Upper_Layer_Details *temp_pdc = ULfirst; pthread_mutex_lock(&mutex_Upper_Layer_Details); while(temp_pdc != NULL ) { temp_pdc->config_change = 1; temp_pdc = temp_pdc->next; } pthread_mutex_unlock(&mutex_Upper_Layer_Details); } else { ptr = tcp_BUF; ptr += 2; copy_cbyc(length,ptr,2); flen = to_intconvertor(length); cal_crc = compute_CRC(tcp_BUF,flen-2); ptr += flen -4; frame_crc = *ptr; frame_crc <<= 8; frame_crc |= *(ptr + 1); if(frame_crc != cal_crc) { continue; } if (sendto(DB_sockfd,tcp_BUF, MAXBUFLEN-1, 0, (struct sockaddr *)&DB_Server_addr,sizeof(DB_Server_addr)) == -1) { perror("sendto"); } tcp_BUF[bytes_read] = '\0'; PMU_process_TCP(tcp_BUF,tcp_sockfd); } } // while ends } }// Main if close(tcp_sockfd); pthread_exit(NULL); } /* ---------------------------------------------------------------------------- */ /* FUNCTION connect_pmu_udp(): */ /* It Makes a new udp connections with each added Lower Layer PMU/PDC. */ /* ---------------------------------------------------------------------------- */ void* connect_pmu_udp(void *temp) { int udp_sockfd,port_num,addr_len,yes = 1; unsigned char *udp_BUF,*ptr,length[2]; unsigned int flen; uint16_t cal_crc,frame_crc; struct sockaddr_in PMU_addr,their_addr; struct Lower_Layer_Details *temp_pmu = (struct Lower_Layer_Details *) temp; struct Lower_Layer_Details *t ; port_num = temp_pmu->port; if ((udp_sockfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) { perror("socket"); exit(1); } if (setsockopt(udp_sockfd,SOL_SOCKET,SO_REUSEADDR,&yes,sizeof(int)) == -1) { perror("setsockopt"); exit(1); } bzero(&PMU_addr,sizeof(PMU_addr)); PMU_addr.sin_family = AF_INET; PMU_addr.sin_addr.s_addr = inet_addr(temp_pmu->ip); PMU_addr.sin_port = htons(port_num); memset(&(PMU_addr.sin_zero), '\0', 8); // zero the rest of the struct /* Copy the information of Lower Layer PMU/PDC to the node */ temp_pmu->thread_id = pthread_self(); bzero(&temp_pmu->llpmu_addr,sizeof(PMU_addr)); temp_pmu->llpmu_addr.sin_family = AF_INET; temp_pmu->llpmu_addr.sin_addr.s_addr = inet_addr(temp_pmu->ip); temp_pmu->llpmu_addr.sin_port = htons(port_num); memset(&(temp_pmu->llpmu_addr.sin_zero), '\0', 8); // zero the rest of the struct temp_pmu->sockfd = udp_sockfd; temp_pmu->up = 1; /* Add PMU*/ add_PMU_Node(temp_pmu); udp_BUF = malloc(MAXBUFLEN* sizeof(unsigned char)); /* Sending Command fro obtaining CFG */ addr_len = sizeof(struct sockaddr); int n,bytes_read; unsigned char *cmdframe = malloc(19); cmdframe[18] = '\0'; create_command_frame(1,temp_pmu->pmuid,(char *)cmdframe); if ((n = sendto(udp_sockfd,cmdframe, 18, 0, (struct sockaddr *)&PMU_addr,sizeof(PMU_addr)) == -1)) { perror("sendto"); } else { free(cmdframe); /* UDP data Received */ while(1) { memset(udp_BUF,'\0',MAXBUFLEN * sizeof(unsigned char)); bytes_read = recvfrom (udp_sockfd, udp_BUF,MAXBUFLEN-1,0,(struct sockaddr *)&their_addr,(socklen_t *)&addr_len); if(bytes_read == -1) { perror("recvfrom"); exit(1); } else { // New Datagram received pthread_mutex_lock(&mutex_Lower_Layer_Details); int flag = 0; if(LLfirst == NULL) { flag = 0; } else { t = LLfirst; while(t != NULL) { if((!strcmp(t->ip,inet_ntoa(their_addr.sin_addr))) && (!strncasecmp(t->protocol,"UDP",3))) { flag = 1; break; } else { t = t->next; } } } pthread_mutex_unlock(&mutex_Lower_Layer_Details); if(flag) { ptr = udp_BUF; ptr += 2; copy_cbyc(length,ptr,2); flen = to_intconvertor(length); cal_crc = compute_CRC(udp_BUF,flen-2); ptr += flen -4; frame_crc = *ptr; frame_crc <<= 8; frame_crc |= *(ptr + 1); if(frame_crc != cal_crc) { continue; } //process the frame int n; if ((n = sendto(DB_sockfd,udp_BUF, MAXBUFLEN-1, 0, (struct sockaddr *)&DB_Server_addr,sizeof(DB_Server_addr)) == -1)) { perror("sendto"); } udp_BUF[bytes_read] = '\0'; //Call the udphandler PMU_process_UDP(udp_BUF,PMU_addr,udp_sockfd); } else { printf("Datagram PMU not authentic. We donot pass the buffer for further processing %s\n",inet_ntoa(their_addr.sin_addr)); } } // Main if ends } // while ends } close(udp_sockfd); pthread_exit(NULL); } /* ---------------------------------------------------------------------------- */ /* FUNCTION add_PMU_Node(): */ /* It creates a node of the type Lower_Layer_Details for each newly added */ /* Lower Layer PMU/PDC. */ /* ---------------------------------------------------------------------------- */ void add_PMU_Node(struct Lower_Layer_Details *temp_pmu) { pthread_mutex_lock(&mutex_Lower_Layer_Details); if(LLfirst == NULL) { temp_pmu->prev = NULL; LLfirst = temp_pmu; } else { LLlast->next = temp_pmu; temp_pmu->prev = LLlast; } temp_pmu->next = NULL; LLlast = temp_pmu; write_cfg_to_file(); pthread_mutex_unlock(&mutex_Lower_Layer_Details); } /* ---------------------------------------------------------------------------- */ /* FUNCTION remove_Lower_Node(): */ /* It sets the remove flag for a Lower Layer PMU/PDC do that it can be removed */ /* later. */ /* ---------------------------------------------------------------------------- */ int remove_Lower_Node(char pmuid[], char protocol[]) { int flag = 0, err; // 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); } if(LLfirst == NULL) { printf("No PMU present?\n"); return 1; } else { flag = 1; } if(flag) { int match = 0; struct Lower_Layer_Details *temp_pmu = LLfirst; while(temp_pmu != NULL) { if(set_all == 1) { match = 1; break; } else { if((temp_pmu->pmuid == atoi(pmuid)) && (!strncasecmp(temp_pmu->protocol,protocol,3))) { match = 1; break; } else { temp_pmu = temp_pmu->next; } } } if(match) { if(set_all == 1) { temp_pmu = LLfirst; while(temp_pmu != NULL) { pthread_t t; if((err = pthread_create(&t,&attr,remove_llnode,(void *)temp_pmu))) { perror(strerror(err)); exit(1); } temp_pmu = temp_pmu->next; } } else { pthread_t t; if((err = pthread_create(&t,&attr,remove_llnode,(void *)temp_pmu))) { perror(strerror(err)); exit(1); } } struct Upper_Layer_Details *temp_pdc = ULfirst; pthread_mutex_lock(&mutex_Upper_Layer_Details); while(temp_pdc != NULL ) { temp_pdc->config_change = 1; temp_pdc = temp_pdc->next; } pthread_mutex_unlock(&mutex_Upper_Layer_Details); return 0; } else { printf("No match for entered PMU\n"); return 1; } } return 1; } /* ---------------------------------------------------------------------------- */ /* FUNCTION remove_llnode(): */ /* ---------------------------------------------------------------------------- */ void* remove_llnode(void* temp) { int flag=0; struct Lower_Layer_Details *temp_pmu = (struct Lower_Layer_Details *) temp; struct Lower_Layer_Details *temp_ptr; pthread_t tid = temp_pmu->thread_id; /* Remove the object from structure 'Lower Layer Details'*/ pthread_mutex_lock(&mutex_Lower_Layer_Details); /* remove the entry from CFG linked list and remove that CFG objects */ /* remove the entry from iPDC Setup File */ if(LLfirst != NULL) { temp_ptr = malloc(sizeof(struct Lower_Layer_Details)); if(!temp_ptr) { printf("Not enough memory temp_pmu\n"); exit(1); } temp_ptr = LLfirst; while (temp_ptr != NULL) { if(((temp_ptr->pmuid == temp_pmu->pmuid)) && (!strcmp(temp_ptr->protocol,temp_pmu->protocol))) { if((temp_ptr->prev != NULL) && (temp_ptr->next != NULL)) //deletion of inbetween node { temp_ptr->prev->next = temp_ptr->next; temp_ptr->next->prev = temp_ptr->prev; temp_ptr = temp_ptr->next; } else if((temp_ptr->prev == NULL) && (temp_ptr->next != NULL)) //deletion of first node { temp_ptr = temp_ptr->next; temp_ptr->prev = NULL; LLfirst = temp_ptr; } else if((temp_ptr->prev != NULL) && (temp_ptr->next == NULL)) //deletion of last node { temp_ptr = temp_ptr->prev; temp_ptr->next = NULL; LLlast = temp_ptr; } else { LLfirst = NULL; LLlast = NULL; } flag = 1; break; } else { temp_ptr = temp_ptr->next; continue; } } } pthread_mutex_unlock(&mutex_Lower_Layer_Details); if(flag == 1) { /* remove the cfg object from memory */ int ind = 0,match = 0; struct cfg_frame *temp_cfg = cfgfirst,*tprev_cfg; unsigned char id_CODE[2]; tprev_cfg = temp_cfg; id_CODE[0] = temp_pmu->pmuid >> 8; id_CODE[1] = temp_pmu->pmuid ; while(temp_cfg != NULL){ if(!ncmp_cbyc(id_CODE,temp_cfg->idcode,2)) { match = 1; break; } else { ind++; tprev_cfg = temp_cfg; temp_cfg = temp_cfg->cfgnext; } }// While ends if(match) { pthread_mutex_lock(&mutex_cfg); if(!ind) { // Replace the cfgfirst cfgfirst = cfgfirst->cfgnext; free_cfgframe_object(temp_cfg); } else { // Replace in between cfg tprev_cfg->cfgnext = temp_cfg->cfgnext; free_cfgframe_object(temp_cfg); } pthread_mutex_unlock(&mutex_cfg); } } pthread_cancel(tid); /* Close the socket connection */ close(temp_pmu->sockfd); free(temp_pmu); write_cfg_to_file(); pthread_exit(NULL); } /* ---------------------------------------------------------------------------- */ /* FUNCTION put_data_transmission_off(): */ /* ---------------------------------------------------------------------------- */ int put_data_transmission_off(char pmuid[], char protocol[]) { int flag = 0,err; // 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); } if((err = pthread_attr_setschedpolicy(&attr,SCHED_FIFO))) { perror(strerror(err)); exit(1); } pthread_mutex_lock(&mutex_Lower_Layer_Details); if(LLfirst == NULL) { printf("No PMU present?\n"); return 1; } else { flag = 1; } pthread_mutex_unlock(&mutex_Lower_Layer_Details); if(flag) { int match = 0; struct Lower_Layer_Details *temp_pmu = LLfirst; while(temp_pmu != NULL) { if(set_all == 1) { match = 1; break; } else { if((temp_pmu->pmuid == atoi(pmuid)) && (!strncasecmp(temp_pmu->protocol,protocol,3))) { match = 1; break; } else { temp_pmu = temp_pmu->next; } } } if(match) { if(set_all == 1) { temp_pmu = LLfirst; while(temp_pmu != NULL) { pthread_t t; temp_pmu->data_transmission_off = 1; if((err = pthread_create(&t,&attr,data_off_llnode,(void *)temp_pmu))) { perror(strerror(err)); exit(1); } temp_pmu = temp_pmu->next; } } else { pthread_t t; temp_pmu->data_transmission_off = 1; if((err = pthread_create(&t,&attr,data_off_llnode,(void *)temp_pmu))) { perror(strerror(err)); exit(1); } } return 0; } else { printf("No match for entered PMU\n"); return 1; } } return 1; } /* ---------------------------------------------------------------------------- */ /* FUNCTION data_off_llnode(): */ /* ---------------------------------------------------------------------------- */ void* data_off_llnode(void* temp) { char *cmdframe = malloc(19); struct Lower_Layer_Details *temp_pmu = (struct Lower_Layer_Details *) temp; create_command_frame(3,temp_pmu->pmuid,cmdframe); cmdframe[18] = '\0'; if(!strncasecmp(temp_pmu->protocol,"UDP",3)) { int n; if ((n = sendto(temp_pmu->sockfd,cmdframe, 18, 0,(struct sockaddr *)&temp_pmu->llpmu_addr,sizeof(temp_pmu->llpmu_addr)) == -1)) { perror("sendto"); } else { printf("Sent CMD to put data transmission OFF\n"); } } else if(!strncasecmp(temp_pmu->protocol,"TCP",3)){ int n; if(temp_pmu->up == 1) { if ((n = send(temp_pmu->sockfd,cmdframe, 18,0) == -1)) { perror("send"); } else { printf("Sent CmD to put data transmission OFF\n"); } } } free(cmdframe); pthread_exit(NULL); } /* ---------------------------------------------------------------------------- */ /* FUNCTION put_data_transmission_on(): */ /* ---------------------------------------------------------------------------- */ int put_data_transmission_on(char pmuid[], char protocol[]) { int flag = 0,err; // 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); } pthread_mutex_lock(&mutex_Lower_Layer_Details); if(LLfirst == NULL) { printf("No PMU Present?\n"); return 1; } else { flag = 1; } pthread_mutex_unlock(&mutex_Lower_Layer_Details); if(flag) { int match = 0; struct Lower_Layer_Details *temp_pmu = LLfirst; while(temp_pmu != NULL) { if(set_all == 1) { match = 1; break; } else { if((temp_pmu->pmuid == atoi(pmuid)) && (!strncasecmp(temp_pmu->protocol,protocol,3))) { match = 1; break; } else { temp_pmu = temp_pmu->next; } } } if(match) { if(set_all == 1) { temp_pmu = LLfirst; while(temp_pmu != NULL) { pthread_t t; temp_pmu->data_transmission_off = 0; if((err = pthread_create(&t,&attr,data_on_llnode,(void *)temp_pmu))) { perror(strerror(err)); exit(1); } temp_pmu = temp_pmu->next; } } else { pthread_t t; temp_pmu->data_transmission_off = 0; if((err = pthread_create(&t,&attr,data_on_llnode,(void *)temp_pmu))) { perror(strerror(err)); exit(1); } } return 0; } else { printf("No match for entered PMU\n"); return 1; } } return 1; } /* ---------------------------------------------------------------------------- */ /* FUNCTION data_on_llnode(): */ /* ---------------------------------------------------------------------------- */ void* data_on_llnode(void* temp) { char *cmdframe = malloc(19); struct Lower_Layer_Details *temp_pmu = (struct Lower_Layer_Details *) temp; create_command_frame(2,temp_pmu->pmuid,cmdframe); cmdframe[18] = '\0'; if(!strncasecmp(temp_pmu->protocol,"UDP",3)) { int n; if ((n = sendto(temp_pmu->sockfd,cmdframe, 18, 0,(struct sockaddr *)&temp_pmu->llpmu_addr,sizeof(temp_pmu->llpmu_addr)) == -1)) { perror("sendto"); } else { printf("Sent CMD to put data transmission ON.\n"); } } else if(!strncasecmp(temp_pmu->protocol,"TCP",3)){ int n; if(temp_pmu->up == 1) { if ((n = send(temp_pmu->sockfd,cmdframe, 18,0) == -1)) { perror("send"); } else { printf("Sent CmD to put data transmission ON.\n"); } } } free(cmdframe); pthread_exit(NULL); } /* ---------------------------------------------------------------------------- */ /* FUNCTION configuration_request(): */ /* ---------------------------------------------------------------------------- */ int configuration_request(char pmuid[], char protocol[]) { int flag = 0,err; // 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); } pthread_mutex_lock(&mutex_Lower_Layer_Details); if(LLfirst == NULL) { printf("No PMU Present?\n"); return 1; } else { flag = 1; } pthread_mutex_unlock(&mutex_Lower_Layer_Details); if(flag) { int match = 0; struct Lower_Layer_Details *temp_pmu = LLfirst; while(temp_pmu != NULL) { if(set_all == 1) { match = 1; break; } else { if((temp_pmu->pmuid == atoi(pmuid)) && (!strncasecmp(temp_pmu->protocol,protocol,3))) { match = 1; break; } else { temp_pmu = temp_pmu->next; } } } if(match) { if(set_all == 1) { temp_pmu = LLfirst; while(temp_pmu != NULL) { pthread_t t; if((err = pthread_create(&t,&attr,config_request,(void *)temp_pmu))) { perror(strerror(err)); exit(1); } temp_pmu = temp_pmu->next; } } else { pthread_t t; if((err = pthread_create(&t,&attr,config_request,(void *)temp_pmu))) { perror(strerror(err)); exit(1); } } return 0; } else { printf("No match for entered PMU\n"); return 1; } } return 1; } /* ---------------------------------------------------------------------------- */ /* FUNCTION config_request(): */ /* ---------------------------------------------------------------------------- */ void* config_request(void* temp) { int err; char *cmdframe = malloc(19); struct Lower_Layer_Details *temp_pmu = (struct Lower_Layer_Details *) temp; 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); } if(!strncasecmp(temp_pmu->protocol,"UDP",3)) { /* If Peer is UDP */ int n; cmdframe[18] = '\0'; create_command_frame(1,temp_pmu->pmuid,cmdframe); if ((n = sendto(temp_pmu->sockfd,cmdframe, 18, 0,(struct sockaddr *)&temp_pmu->llpmu_addr,sizeof(temp_pmu->llpmu_addr)) == -1)) { perror("sendto"); } else { free(cmdframe); temp_pmu->data_transmission_off = 0; } } else if(!strncasecmp(temp_pmu->protocol,"TCP",3)){ /* If Peer is TCP */ int n; if(temp_pmu->up == 0) { /* If TCP Peer is DOWN */ pthread_t t; if((err = pthread_create(&t,&attr,connect_pmu_tcp,(void *)temp_pmu))) { perror(strerror(err)); exit(1); } struct Upper_Layer_Details *temp_pdc = ULfirst; pthread_mutex_lock(&mutex_Upper_Layer_Details); while(temp_pdc != NULL ) { temp_pdc->config_change = 1; temp_pdc = temp_pdc->next; } pthread_mutex_unlock(&mutex_Upper_Layer_Details); } else { /* If TCP Peer is UP */ cmdframe[18] = '\0'; create_command_frame(1,temp_pmu->pmuid,cmdframe); if ((n = send(temp_pmu->sockfd,cmdframe, 18,0) == -1)) { printf("temp_pmu->sockfd %d \n",temp_pmu->sockfd); perror("send"); } else { printf("CMD to send CFG \n"); free(cmdframe); temp_pmu->data_transmission_off = 0; } } } pthread_exit(NULL); } /* ---------------------------------------------------------------------------- */ /* FUNCTION add_PDC((char ip[], char protocol[]): */ /* It Makes an entry in iPDC Setup File for the upper PDC. The pre-existing */ /* entry will be removed from the file and also the list Upper_Layer_Details */ /* ---------------------------------------------------------------------------- */ int add_PDC(char ip[], char protocol[]) { int flag = 0; struct Upper_Layer_Details *temp_ptr; pthread_mutex_lock(&mutex_Upper_Layer_Details); if(ULfirst != NULL) { temp_ptr = malloc(sizeof(struct Upper_Layer_Details)); if(!temp_ptr) { printf("Not enough memory temp_pmu\n"); exit(1); } temp_ptr = ULfirst; while (temp_ptr != NULL) { if((!strcmp(temp_ptr->ip, ip)) && (!strncasecmp(temp_ptr->protocol, protocol, 3))) { flag = 1; break; } else { temp_ptr = temp_ptr->next; continue; } } } if(flag) /* 2 if there is a match */ { printf("%s %s is already in the UpperDevices list Enter another PDC.\n",ip,protocol); return 1; } else if(!flag) { /* Make a node that contains PMU IP, Port and Protocol details */ struct Upper_Layer_Details *temp_pdc; temp_pdc = malloc(sizeof(struct Upper_Layer_Details)); if(!temp_pdc) { printf("Not enough memory temp_pdc\n"); exit(1); } strcpy(temp_pdc->ip,ip); // ip if(!strncasecmp(protocol,"UDP",3)) { temp_pdc->port = UDPPORT; // port } else { temp_pdc->port = TCPPORT; // port } strncpy(temp_pdc->protocol,protocol,3); // protocol temp_pdc->protocol[3] = '\0'; 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->tcpup = 1; temp_pdc->UL_upper_pdc_cfgsent = 0; temp_pdc->UL_data_transmission_off = 1; temp_pdc->address_set = 0; 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; write_cfg_to_file(); } pthread_mutex_unlock(&mutex_Upper_Layer_Details); return 0; } /* ---------------------------------------------------------------------------- */ /* FUNCTION remove_PDC((char ip[], char port_num[], char protocol[]): */ /* ---------------------------------------------------------------------------- */ int remove_PDC(char ip[], char port_num[], char protocol[]) { int flag = 0; struct Upper_Layer_Details *temp_pdc; if(ULfirst == NULL) { printf("No PDC Present?\n"); return 1; } else { temp_pdc = malloc(sizeof(struct Upper_Layer_Details)); temp_pdc = ULfirst; while(temp_pdc != NULL) { if(!strcmp(temp_pdc->ip,ip)) { if(((!strncasecmp(temp_pdc->protocol,"UDP",3)) && (temp_pdc->port == UDPPORT)) || ((!strncasecmp(temp_pdc->protocol,"TCP",3)) && (temp_pdc->port == TCPPORT))) { flag = 1; break; } } temp_pdc = temp_pdc->next; } if(flag == 1) { pthread_mutex_lock(&mutex_Upper_Layer_Details); if(temp_pdc->prev == NULL) { ULfirst = temp_pdc->next; if(ULfirst != NULL) ULfirst->prev = NULL; } else { temp_pdc->prev->next = temp_pdc->next; } if(temp_pdc->next == NULL) { ULlast = temp_pdc->prev; } else { if(temp_pdc->prev != NULL) temp_pdc->prev->next = temp_pdc->next; } write_cfg_to_file(); pthread_mutex_unlock(&mutex_Upper_Layer_Details); return 0; } return 1; } } /* ---------------------------------------------------------------------------- */ /* FUNCTION display_CT(): */ /* ---------------------------------------------------------------------------- */ void display_CT() { printf("#### CONNECTION TABLE OF SOURCE DEVICES ####\n"); printf("--------------------------------------------------------------------------------\n"); printf("| PMU ID | IP | Port | Protocol | Up |\n"); printf("--------------------------------------------------------------------------------\n"); pthread_mutex_lock(&mutex_Lower_Layer_Details); if(LLfirst == NULL) { printf("No PMU Present?\n"); } else { struct Lower_Layer_Details *t = LLfirst; while(t != NULL) { printf("|\t%d\t|%s\t|\t%d\t|\t%s\t|\t%d\t|\n",t->pmuid,t->ip,t->port,t->protocol,t->up); t = t->next; } printf("--------------------------------------------------------------------------------\n"); } pthread_mutex_unlock(&mutex_Lower_Layer_Details); printf("#### CONNECTION TABLE OF DESTINATION DEVICES ####\n"); printf("-------------------------------------------------\n"); printf("| IP | Port | Protocol |\n"); printf("-------------------------------------------------\n"); if(ULfirst == NULL) { printf("No PDC Present?\n"); } else { struct Upper_Layer_Details *t = ULfirst; while(t != NULL) { printf("|%s\t|\t%d\t|\t%s\t|\n",t->ip,t->port,t->protocol); t = t->next; } printf("-------------------------------------------------\n"); } } /* ---------------------------------------------------------------------------- */ /* FUNCTION create_command_frame(): */ /* ---------------------------------------------------------------------------- */ void create_command_frame(int type,int pmu_id,char cmdframe[]) { int f = 18; long int sec,frac = 0; unsigned char fsize[2],pmuid[2],soc[4],fracsec[4]; uint16_t chk; memset(cmdframe,'\0',19); memset(fsize,'\0',2); int_to_ascii_convertor(f,fsize); int_to_ascii_convertor(pmu_id,pmuid); sec = (long int)time (NULL); long_int_to_ascii_convertor(sec,soc); long_int_to_ascii_convertor(frac,fracsec); int index = 0; switch(type) { case 1 : byte_by_byte_copy((unsigned char *)cmdframe,CMDSYNC,index,2); // SEND CFG index += 2; byte_by_byte_copy((unsigned char *)cmdframe,fsize,index,2); index += 2; byte_by_byte_copy((unsigned char *)cmdframe,pmuid,index,2); index += 2; byte_by_byte_copy((unsigned char *)cmdframe,soc,index,4); index += 4; byte_by_byte_copy((unsigned char *)cmdframe,fracsec,index,4); index += 4; byte_by_byte_copy((unsigned char *)cmdframe,CMDCFGSEND,index,2); index += 2; chk = compute_CRC((unsigned char *)cmdframe,index); cmdframe[index++] = (chk >> 8) & ~(~0<<8); /* CHKSUM high byte; */ cmdframe[index] = (chk ) & ~(~0<<8); /* CHKSUM low byte; */ break; case 2 : byte_by_byte_copy((unsigned char *)cmdframe,CMDSYNC,index,2); // SEND DATA ON index += 2; byte_by_byte_copy((unsigned char *)cmdframe,fsize,index,2); index += 2; byte_by_byte_copy((unsigned char *)cmdframe,pmuid,index,2); index += 2; byte_by_byte_copy((unsigned char *)cmdframe,soc,index,4); index += 4; byte_by_byte_copy((unsigned char *)cmdframe,fracsec,index,4); index += 4; byte_by_byte_copy((unsigned char *)cmdframe,CMDDATASEND,index,2); index += 2; chk = compute_CRC((unsigned char *)cmdframe,index); cmdframe[index++] = (chk >> 8) & ~(~0<<8); /* CHKSUM high byte; */ cmdframe[index] = (chk ) & ~(~0<<8); /* CHKSUM low byte; */ break; case 3 : byte_by_byte_copy((unsigned char *)cmdframe,CMDSYNC,index,2); // PUT OFF DATA TRANSMISSION index += 2; byte_by_byte_copy((unsigned char *)cmdframe,fsize,index,2); index += 2; byte_by_byte_copy((unsigned char *)cmdframe,pmuid,index,2); index += 2; byte_by_byte_copy((unsigned char *)cmdframe,soc,index,4); index += 4; byte_by_byte_copy((unsigned char *)cmdframe,fracsec,index,4); index += 4; byte_by_byte_copy((unsigned char *)cmdframe,CMDDATAOFF,index,2); index += 2; chk = compute_CRC((unsigned char *)cmdframe,index); cmdframe[index++] = (chk >> 8) & ~(~0<<8); /* CHKSUM high byte; */ cmdframe[index] = (chk ) & ~(~0<<8); /* CHKSUM low byte; */ break; default: printf("Please enter a valid request?\n"); break; } } /* ---------------------------------------------------------------------------- */ /* FUNCTION checkip(): */ /* ---------------------------------------------------------------------------- */ int checkip(char ip[]) { struct sockaddr_in sa; int result = inet_pton(AF_INET, ip, &(sa.sin_addr)); return result; } /**************************************** End of File *******************************************************/