FACT++  1.0
void command_handler ( int *  tag,
char *  address,
int *  size 
)

Definition at line 829 of file feeserver.c.

References calculateChecksum(), checkCommand(), createBenchmark(), createLogMessage(), dis_update_service, fee_exit_handler(), findMemoryNode(), Memory::free(), freeMemoryNode(), getDeadband(), getIssueTimeout(), getLogLevel(), getUpdateRate(), initIssueStruct(), leaveCommandHandler(), Memory::malloc(), marshallHeader(), restartFeeServer(), setDeadband(), setIssueTimeout(), setLogLevel(), setUpdateRate(), sprintf(), threadIssue(), unlockIssueMutex(), and updateFeeServer().

Referenced by start().

829  {
830  struct timeval now;
831  struct timespec timeout;
832  int retcode = -1;
833  int status = -1;
834  pthread_t thread_handle;
835  pthread_attr_t attr;
836  IssueStruct issueParam;
837  CommandHeader header;
838  char* pHeaderStream = 0;
839  MemoryNode* memNode = 0;
840  bool useMM = false;
841 
842 #ifdef __BENCHMARK
843  char benchmsg[200];
844  // make benchmark entry
845  if ((size != 0 ) && (*size >= 4)) {
846  benchmsg[sprintf(benchmsg,
847  "FeeServer CommandHandler (Received command) - Packet-ID: %d",
848  *address)] = 0;
849  createBenchmark(benchmsg);
850  } else {
851  createBenchmark("FeeServer CommandHandler (Received command)");
852  }
853 #endif
854 
855  // init struct
856  initIssueStruct(&issueParam);
857 
858  issueParam.nRet = FEE_UNKNOWN_RETVAL;
859 
860  // check state (ERROR state is allowed for FeeServer commands, not CE)
861  if ((state != RUNNING) && (state != ERROR_STATE)) {
862  return;
863  }
864 
865  // lock command mutex to save command &ACK data until it is send
866  // and only one CE-Thread exists at one time
867  status = pthread_mutex_lock(&command_mut);
868  if (status != 0) {
869 # ifdef __DEBUG
870  printf("Lock command mutex error: %d\n", status);
871  fflush(stdout);
872 # endif
873  createLogMessage(MSG_WARNING, "Unable to lock command mutex.", 0);
874  }
875 
876  if ((tag == 0) || (address == 0) || (size == 0)) {
877  leaveCommandHandler(0, FEE_NULLPOINTER, MSG_WARNING,
878  "Received null pointer of DIM framework in command handler.");
879  return;
880  }
881 
882  if (*size < HEADER_SIZE) {
883  leaveCommandHandler(0, FEE_INVALID_PARAM, MSG_WARNING,
884  "FeeServer received corrupted command.");
885  return;
886  }
887 
888 # ifdef __DEBUG
889  printf(" Cmnd - Size: %d\n", *size);
890  fflush(stdout);
891 # endif
892 
893  //-- storing the header information in struct --
894  memcpy(&header.id, address, HEADER_SIZE_ID);
895  memcpy(&header.errorCode, address + HEADER_OFFSET_ID, HEADER_SIZE_ERROR_CODE);
896  memcpy(&header.flags, address + HEADER_OFFSET_ERROR_CODE, HEADER_SIZE_FLAGS);
897  memcpy(&header.checksum, address + HEADER_OFFSET_FLAGS, HEADER_SIZE_CHECKSUM);
898 
899  // --------------------- Check Flags --------------------------
900  if ((header.flags & HUFFMAN_FLAG) != 0) {
901  //-- do Huffmann decoding if flag is set --
902  // not implemented yet !!!
903  }
904 
905  issueParam.size = *size - HEADER_SIZE;
906  issueParam.command = (address + HEADER_SIZE);
907  // !!! if Huffman decoding necessary, think about memory management ???
908 
909  if ((header.flags & CHECKSUM_FLAG) != 0) {
910  //-- do checksum test if flag is set --
911  if (!checkCommand(issueParam.command, issueParam.size, header.checksum)) {
912  // -- checksum failed - notification
913  leaveCommandHandler(header.id, FEE_CHECKSUM_FAILED, MSG_WARNING,
914  "FeeServer received corrupted command data (checksum failed).");
915  return;
916  }
917  }
918 
919  // -- here start the Commands for the FeeServer itself --
920  if ((header.flags & FEESERVER_UPDATE_FLAG) != 0) {
921 #ifdef ENABLE_MASTERMODE
922  updateFeeServer(&issueParam);
923 #else
924  createLogMessage(MSG_WARNING, "FeeServer is not authorized to execute shell programs, skip ...", 0);
925 #endif //ENABLE_MASTERMODE
926  // this is only reached, if update has not been sucessful
927  issueParam.nRet = FEE_FAILED;
928  issueParam.size = 0;
929  } else if ((header.flags & FEESERVER_RESTART_FLAG) != 0) {
931  } else if ((header.flags & FEESERVER_REBOOT_FLAG) != 0) {
932  createLogMessage(MSG_INFO, "Rebooting DCS board.", 0);
933  system("reboot");
934  exit(0);
935  } else if ((header.flags & FEESERVER_SHUTDOWN_FLAG) != 0) {
936  createLogMessage(MSG_INFO, "Shuting down DCS board.", 0);
937  system("poweroff");
938  exit(0);
939  } else if ((header.flags & FEESERVER_EXIT_FLAG) != 0) {
940  fee_exit_handler(0);
941  } else if ((header.flags & FEESERVER_SET_DEADBAND_FLAG) != 0) {
942  issueParam.nRet = setDeadband(&issueParam);
943  } else if ((header.flags & FEESERVER_GET_DEADBAND_FLAG) != 0) {
944  issueParam.nRet = getDeadband(&issueParam);
945  } else if ((header.flags & FEESERVER_SET_ISSUE_TIMEOUT_FLAG) != 0) {
946  issueParam.nRet = setIssueTimeout(&issueParam);
947  } else if ((header.flags & FEESERVER_GET_ISSUE_TIMEOUT_FLAG) != 0) {
948  issueParam.nRet = getIssueTimeout(&issueParam);
949  } else if ((header.flags & FEESERVER_SET_UPDATERATE_FLAG) != 0) {
950  issueParam.nRet = setUpdateRate(&issueParam);
951  } else if ((header.flags & FEESERVER_GET_UPDATERATE_FLAG) != 0) {
952  issueParam.nRet = getUpdateRate(&issueParam);
953  } else if ((header.flags & FEESERVER_SET_LOGLEVEL_FLAG) != 0) {
954  issueParam.nRet = setLogLevel(&issueParam);
955  } else if ((header.flags & FEESERVER_GET_LOGLEVEL_FLAG) != 0) {
956  issueParam.nRet = getLogLevel(&issueParam);
957  } else {
958  // commands for CE are not allowed in ERROR state
959  if (state == ERROR_STATE) {
960  leaveCommandHandler(header.id, FEE_WRONG_STATE, MSG_ERROR,
961  "FeeServer is in ERROR_STATE, ignoring command for CE!");
962  return;
963  }
964 
965  // packet with no flags in header and no payload makes no sense
966  if (issueParam.size == 0) {
967  leaveCommandHandler(header.id, FEE_INVALID_PARAM, MSG_WARNING,
968  "FeeServer received empty command.");
969  return;
970  }
971 
972  // lock mutex
973  status = pthread_mutex_lock(&wait_mut);
974  if (status != 0) {
975  leaveCommandHandler(header.id, FEE_THREAD_ERROR, MSG_ERROR,
976  "Unable to lock condition mutex for watchdog.");
977  return;
978  }
979 
980  status = pthread_attr_init(&attr);
981  if (status != 0) {
983  leaveCommandHandler(header.id, FEE_THREAD_ERROR, MSG_ERROR,
984  "Unable to initialize issue thread.");
985  return;
986  }
987 
988  status = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
989  if (status != 0) {
991  leaveCommandHandler(header.id, FEE_THREAD_ERROR, MSG_ERROR,
992  "Unable to initialize issue thread.");
993  return;
994  }
995 
996  status = pthread_create(&thread_handle, &attr, &threadIssue, (void*) &issueParam);
997  if (status != 0) {
999  leaveCommandHandler(header.id, FEE_THREAD_ERROR, MSG_ERROR,
1000  "Unable to create issue thread.");
1001  return;
1002  }
1003 
1004  status = pthread_attr_destroy(&attr);
1005  if (status != 0) {
1006 # ifdef __DEBUG
1007  printf("Destroy attribute error: %d\n", status);
1008  fflush(stdout);
1009 # endif
1010  createLogMessage(MSG_WARNING,
1011  "Unable to destroy thread attribute.", 0);
1012  }
1013 
1014  // timeout set in ms, see fee_defines.h for current value
1015  status = gettimeofday(&now, 0);
1016  if (status == 0) {
1017  // issueTimeout is in milliseconds:
1018  // get second-part with dividing by 1000
1019  timeout.tv_sec = now.tv_sec + (int) (issueTimeout / 1000);
1020  // get rest of division by 1000 (which is milliseconds)
1021  // and make it nanoseconds
1022  timeout.tv_nsec = (now.tv_usec * 1000) +
1023  ((issueTimeout % 1000) * 1000000);
1024 
1025  // wait for finishing "issue" or timeout, if signal has been sent
1026  // retcode is 0 !
1027  // this is the main logic of the watchdog for the CE of the FeeServer
1028  retcode = pthread_cond_timedwait(&cond, &wait_mut, &timeout);
1029 # ifdef __DEBUG
1030  printf("Retcode of CMND timedwait: %d\n", retcode);
1031  fflush(stdout);
1032 # endif
1033 
1034  // check retcode to detect and handle Timeout
1035  if (retcode == ETIMEDOUT) {
1036 # ifdef __DEBUG
1037  printf("ControlEngine watchdog detected TimeOut.\n");
1038  fflush(stdout);
1039 # endif
1040  createLogMessage(MSG_WARNING,
1041  "ControlEngine watch dog noticed a time out for last command.", 0);
1042 
1043  // kill not finished thread. no problem if this returns an error
1044  pthread_cancel(thread_handle);
1045  // setting errorCode to "a timout occured"
1046  issueParam.nRet = FEE_TIMEOUT;
1047  issueParam.size = 0;
1048  } else if (retcode != 0) {
1049  // "handling" of other error than timeout
1050 # ifdef __DEBUG
1051  printf("ControlEngine watchdog detected unknown error.\n");
1052  fflush(stdout);
1053 # endif
1054  createLogMessage(MSG_WARNING,
1055  "ControlEngine watch dog received an unknown for last command.", 0);
1056 
1057  // kill not finished thread. no problem if this returns an error
1058  pthread_cancel(thread_handle);
1059  // setting errorCode to "a thread error occured"
1060  issueParam.nRet = FEE_THREAD_ERROR;
1061  issueParam.size = 0;
1062  }
1063 
1064  } else {
1065 # ifdef __DEBUG
1066  printf("Get time of day error: %d\n", status);
1067  fflush(stdout);
1068 # endif
1069  createLogMessage(MSG_WARNING,
1070  "Watchdog timer could not be initialized. Using non-reliable sleep instead.",
1071  0);
1072  // release mutex to avoid hang up in issueThread before signaling condition
1073  unlockIssueMutex();
1074  // watchdog with condition signal could not be used, because gettimeofday failed.
1075  // sleeping instead for usual amount of time and trying to cancel thread aftterwards.
1076  usleep(issueTimeout * 1000);
1077  status = pthread_cancel(thread_handle);
1078  // if thread did still exist something went wrong -> "timeout" (== 0)
1079  if (status == 0) {
1080 # ifdef __DEBUG
1081  printf("TimeOut occured.\n");
1082 # endif
1083  createLogMessage(MSG_WARNING,
1084  "ControlEngine issue did not return in time.", 0);
1085  issueParam.nRet = FEE_TIMEOUT;
1086  issueParam.size = 0;
1087  }
1088  }
1089 
1090  unlockIssueMutex();
1091  }
1092  //--- end of CE call area --------------------
1093 
1094  // ---------- start to compose result -----------------
1095 # ifdef __DEBUG
1096  printf("Issue-nRet: %d\n", issueParam.nRet);
1097  fflush(stdout);
1098 # endif
1099  // check return value of issue
1100  if ((issueParam.nRet < FEE_UNKNOWN_RETVAL) ||
1101  (issueParam.nRet > FEE_MAX_RETVAL)) {
1102  issueParam.nRet = FEE_UNKNOWN_RETVAL;
1103  createLogMessage(MSG_DEBUG,
1104  "ControlEngine [command] returned unkown RetVal.", 0);
1105  }
1106 
1107 // start here with new memory management check for ACK
1108  // check if old ACK data is in MemoryNode list and free it
1109  if ((cmndACKSize > HEADER_SIZE) && (findMemoryNode(cmndACK + HEADER_SIZE) != 0)) {
1110  memNode = findMemoryNode(cmndACK + HEADER_SIZE);
1111  freeMemoryNode(memNode);
1112  } else { // free cmndACK in original way
1113  if (cmndACK != 0) {
1114  free(cmndACK);
1115  cmndACK = 0;
1116  }
1117  }
1118 
1119  // check if new result data is in MemoryNode list
1120  memNode = findMemoryNode(issueParam.result);
1121  if (memNode != 0) {
1122  cmndACK = memNode->ptr;
1123  useMM = true;
1124  } else {
1125  // create Acknowledge as return value of command
1126  // HEADER_SIZE bytes are added before result to insert the command
1127  // header before the result -> see CommandHeader in Client for details
1128  cmndACK = (char*) malloc(issueParam.size + HEADER_SIZE);
1129  }
1130 
1131  if (cmndACK == 0) {
1132  //no memory available!
1133 # ifdef __DEBUG
1134  printf("no memory available!\n");
1135  fflush(stdout);
1136 # endif
1137  createLogMessage(MSG_ERROR, "Insufficient memory for ACK.", 0);
1138 
1139  // no ACK because no memory!
1140  cmndACKSize = 0;
1141  status = pthread_mutex_unlock(&command_mut);
1142  if (status != 0) {
1143 # ifdef __DEBUG
1144  printf("Lock command mutex error: %d\n", status);
1145  fflush(stdout);
1146 # endif
1147  createLogMessage(MSG_WARNING,
1148  "Error while trying to unlock command mutex.", 0);
1149  }
1150  return;
1151  }
1152 
1153 # ifdef __DEBUG
1154  if (issueParam.size > 0) {
1155 // printf("in cmnd-Handler -> issue result: ");
1156 // printData(issueParam.result, 0, issueParam.size);
1157 // fflush(stdout);
1158  }
1159 # endif
1160 
1161  // checks checksumflag and calculates it if necessary
1162  if ((header.flags & CHECKSUM_FLAG) != 0) {
1163  header.checksum = calculateChecksum((unsigned char*) issueParam.result,
1164  issueParam.size);
1165  // !!! Do (Huffman- ) encoding, if wished afterwards.
1166  } else {
1167  header.checksum = CHECKSUM_ZERO;
1168  }
1169 
1170  // keep the whole flags also for the result packet
1171  header.errorCode = (short) issueParam.nRet;
1172 # ifdef __DEBUG
1173  printf("ErrorCode in Header: %d\n", header.errorCode);
1174  fflush(stdout);
1175 # endif
1176 
1177  pHeaderStream = marshallHeader(&header);
1178  memcpy((void*) cmndACK, (void*) pHeaderStream, HEADER_SIZE);
1179  if (pHeaderStream != 0) {
1180  free(pHeaderStream);
1181  }
1182 
1183  if (useMM) {
1184  /*
1185 # ifdef __DEBUG
1186  printf("ACK channel used with MemoryManagement in FeeServer.\n");
1187  fflush(stdout);
1188  createLogMessage(MSG_DEBUG,
1189  "ACK channel used with MemoryManagement in FeeServer.", 0);
1190 # endif
1191  */
1192  } else {
1193  memcpy(((void*) cmndACK + HEADER_SIZE), (void*) issueParam.result,
1194  issueParam.size);
1195  }
1196 
1197  //store the size of the result globally
1198  cmndACKSize = issueParam.size + HEADER_SIZE;
1199  // propagate change of ACK(nowledge channel) to upper Layers
1201 
1202 # ifdef __DEBUG
1203  // -- see the cmndACK as a char - string
1204  printf("ACK \n");
1205 // printData(cmndACK, HEADER_SIZE, cmndACKSize);
1206  // -- see the cmndACK in a HEX view for the ALTRO
1207  //print_package(cmndACK + HEADER_SIZE);
1208 # endif
1209 
1210  if ((!useMM) && (issueParam.result != 0)) {
1211  free(issueParam.result);
1212  }
1213 // end of new stuff for memory managment.
1214 
1215 /*
1216  if (cmndACK != 0) {
1217  free(cmndACK);
1218  cmndACK = 0;
1219  }
1220  // create Acknowledge as return value of command
1221  // HEADER_SIZE bytes are added before result to insert the command
1222  // header before the result -> see CommandHeader in Client for details
1223  cmndACK = (char*) malloc(issueParam.size + HEADER_SIZE);
1224  if (cmndACK == 0) {
1225  //no memory available!
1226 # ifdef __DEBUG
1227  printf("no memory available!\n");
1228  fflush(stdout);
1229 # endif
1230  createLogMessage(MSG_ERROR, "Insufficient memory for ACK.", 0);
1231 
1232  // no ACK because no memory!
1233  cmndACKSize = 0;
1234  status = pthread_mutex_unlock(&command_mut);
1235  if (status != 0) {
1236 # ifdef __DEBUG
1237  printf("Lock command mutex error: %d\n", status);
1238  fflush(stdout);
1239 # endif
1240  createLogMessage(MSG_WARNING,
1241  "Error while trying to unlock command mutex.", 0);
1242  }
1243  return;
1244  }
1245 
1246 # ifdef __DEBUG
1247  if (issueParam.size > 0) {
1248 // printf("in cmnd-Handler -> issue result: ");
1249 // printData(issueParam.result, 0, issueParam.size);
1250 // fflush(stdout);
1251  }
1252 # endif
1253 
1254  // checks checksumflag and calculates it if necessary
1255  if ((header.flags & CHECKSUM_FLAG) != 0) {
1256  header.checksum = calculateChecksum((unsigned char*) issueParam.result,
1257  issueParam.size);
1258  // !!! Do (Huffman- ) encoding, if wished afterwards.
1259  } else {
1260  header.checksum = CHECKSUM_ZERO;
1261  }
1262 
1263  // keep the whole flags also for the result packet
1264  header.errorCode = (short) issueParam.nRet;
1265 # ifdef __DEBUG
1266  printf("ErrorCode in Header: %d\n", header.errorCode);
1267  fflush(stdout);
1268 # endif
1269 
1270  pHeaderStream = marshallHeader(&header);
1271  memcpy((void*) cmndACK, (void*) pHeaderStream, HEADER_SIZE);
1272  if (pHeaderStream != 0) {
1273  free(pHeaderStream);
1274  }
1275  memcpy(((void*) cmndACK + HEADER_SIZE), (void*) issueParam.result,
1276  issueParam.size);
1277 
1278  //store the size of the result globally
1279  cmndACKSize = issueParam.size + HEADER_SIZE;
1280  // propagate change of ACK(nowledge channel) to upper Layers
1281  dis_update_service(serviceACKID);
1282 
1283 # ifdef __DEBUG
1284  // -- see the cmndACK as a char - string
1285  printf("ACK \n");
1286 // printData(cmndACK, HEADER_SIZE, cmndACKSize);
1287  // -- see the cmndACK in a HEX view for the ALTRO
1288  //print_package(cmndACK + HEADER_SIZE);
1289 # endif
1290 
1291  if (issueParam.result != 0) {
1292  free(issueParam.result);
1293  }
1294 
1295 */
1296 
1297 
1298  // unlock command mutex, data has been sent
1299  status = pthread_mutex_unlock(&command_mut);
1300  if (status != 0) {
1301 # ifdef __DEBUG
1302  printf("Lock command mutex error: %d\n", status);
1303  fflush(stdout);
1304 # endif
1305  createLogMessage(MSG_WARNING,
1306  "Error while trying to unlock command mutex.", 0);
1307  }
1308 }
unsigned int calculateChecksum(unsigned char *buffer, int size)
Definition: feeserver.c:2372
int setUpdateRate(IssueStruct *issueParam)
Definition: feeserver.c:2719
void fee_exit_handler(unsigned int state)
Definition: feeserver.c:3109
void * malloc()
Definition: EventBuilder.cc:99
void initIssueStruct(IssueStruct *issueStr)
Definition: feeserver.c:2993
int setLogLevel(IssueStruct *issueParam)
Definition: feeserver.c:2768
static unsigned int serviceACKID
Definition: feeserver.c:153
MemoryNode * findMemoryNode(void *addr)
Definition: feeserver.c:3691
void updateFeeServer(IssueStruct *issueParam)
Definition: feeserver.c:2417
void createLogMessage(unsigned int type, char *description, char *origin)
Definition: feeserver.c:1530
int getUpdateRate(IssueStruct *issueParam)
Definition: feeserver.c:2745
static pthread_mutex_t wait_mut
Definition: feeserver.c:254
static pthread_mutex_t command_mut
Definition: feeserver.c:266
void unlockIssueMutex()
Definition: feeserver.c:1378
#define dis_update_service
Definition: dis.h:18
int setIssueTimeout(IssueStruct *issueParam)
Definition: feeserver.c:2662
static char * cmndACK
Definition: feeserver.c:171
static pthread_cond_t cond
Definition: feeserver.c:242
int getDeadband(IssueStruct *issueParam)
Definition: feeserver.c:2586
int size
Definition: db_dim_server.c:17
void freeMemoryNode(MemoryNode *node)
Definition: feeserver.c:3812
int setDeadband(IssueStruct *issueParam)
Definition: feeserver.c:2494
void free(void *mem)
static int cmndACKSize
Definition: feeserver.c:177
void createBenchmark(char *msg)
Definition: feeserver.c:4335
void leaveCommandHandler(unsigned int id, short errorCode, unsigned int msgType, char *message)
Definition: feeserver.c:1344
void restartFeeServer()
Definition: feeserver.c:2463
static unsigned long issueTimeout
Definition: feeserver.c:203
void * threadIssue(void *threadParam)
Definition: feeserver.c:2243
bool checkCommand(char *payload, int size, unsigned int checksum)
Definition: feeserver.c:2352
sprintf(name1,"NewService%d", i)
char * marshallHeader(CommandHeader *pHeader)
Definition: feeserver.c:2389
int getIssueTimeout(IssueStruct *issueParam)
Definition: feeserver.c:2697
int getLogLevel(IssueStruct *issueParam)
Definition: feeserver.c:2826

+ Here is the call graph for this function:

+ Here is the caller graph for this function: