00001
00002 #include <signal.h>
00003 #include <unistd.h>
00004 #include <stdio.h>
00005 #include "dataclient.h"
00006 #include "errcode.h"
00007
00008 DataClient::DataClient()
00009 {
00010 keytable = new KeyTable;
00011 connected = false;
00012 portnum = 0;
00013 strcpy(servername, "");
00014 }
00015
00016 DataClient::DataClient(char *host, int port)
00017 {
00018 keytable = new KeyTable;
00019 connected = false;
00020 portnum = 0;
00021 strcpy(servername, "");
00022 Connect(host, port);
00023 }
00024
00025 DataClient::~DataClient()
00026 {
00027 Disconnect();
00028 delete keytable;
00029 }
00030
00031 int DataClient::Connect(char *host, int port)
00032 {
00033
00034 signal(SIGPIPE, SIG_IGN);
00035 signal(SIGABRT, SIG_IGN);
00036
00037 if (!TCPSocket::Connect(host, port))
00038 {
00039
00040
00041 return POSSE_RETRY;
00042 }
00043
00044 int a;
00045 try
00046 {
00047 SendClientName();
00048 int size = QueryKeyword("_start_private");
00049 a = RecvVar<int>();
00050 }
00051 catch (int &e)
00052 {
00053 if (e == ERR_RECV_MESG)
00054 {
00055 #ifdef ANIDEBUG
00056 cerr << "DataClient: Error: Initialization failed!! " << endl;
00057 cerr << "\tNo DataServer listening on " << host << ":" << port << endl << flush;
00058 cerr << "\tExiting!" << endl;
00059 #endif
00060 }
00061 return POSSE_FAILURE;
00062 }
00063
00064 if (a != VERIFICATION_NUMBER)
00065 {
00066 cerr << "DataClient: Error: Initialization failed!! ";
00067 cerr << "[Recd " << a << ", expected " << VERIFICATION_NUMBER << "]!" << endl << flush;
00068 cerr << "\tExiting!" << endl;
00069 return POSSE_FAILURE;
00070 }
00071
00072 RecvKeyTable(keytable);
00073
00074 connected = true;
00075 portnum = port;
00076 strcpy(servername, host);
00077
00078 return POSSE_SUCCESS;
00079 }
00080
00081 int DataClient::Disconnect()
00082 {
00083 int a = 0;
00084 if (connected)
00085 {
00086 try {
00087 a = SendKeyword("_q_private");
00088 TCPSocket::Close();
00089 }
00090 catch (int &err)
00091 {
00092 cout << "DataClient::Disconnect(): Caught exception!!" << endl << flush;
00093 }
00094 }
00095 portnum = 0;
00096 strcpy(servername, "");
00097 return a;
00098 }
00099
00100 int DataClient::RecvKeyTable(KeyTable *K)
00101 {
00102 if (K == NULL)
00103 K = keytable;
00104 SendKeyword("keytable");
00105 RemoteSocket::RecvStruct(K);
00106 return 1;
00107 }
00108
00109 VariableType DataClient::VarType(char *keyword)
00110 {
00111 int handle = keytable->getKeyHandle(keyword);
00112 if (handle == keytable->n)
00113 {
00114 cout << "Error: Unknown keyword \"" << keyword << "\"!!" << endl << flush;
00115 return UNKNOWN;
00116 }
00117
00118 return keytable->key[handle].vartype;
00119 }
00120
00121 char *DataClient::RecvValue(char *keyword)
00122 {
00123 char *val = new char[100];
00124 VariableType vtype = UNKNOWN;
00125
00126 int handle = keytable->getKeyHandle(keyword);
00127 if (handle < keytable->n && keytable->isViewableVar(handle))
00128 vtype = keytable->key[handle].vartype;
00129
00130 switch (vtype)
00131 {
00132 case CHAR:
00133 if (keytable->isCharArray(handle))
00134 {
00135 char s[100];
00136 RecvArray(keyword, s);
00137 memcpy(val, s, 99);
00138 val[99] = '\0';
00139 }
00140 else
00141 {
00142 char x_char;
00143 RecvVariable(keyword, &x_char);
00144 sprintf(val, "%c\0", x_char);
00145 }
00146 break;
00147
00148 case SHORT:
00149 short x_short;
00150 RecvVariable(keyword, &x_short);
00151 sprintf(val, "%d\0", x_short);
00152 break;
00153
00154 case INT:
00155 int x_int;
00156 RecvVariable(keyword, &x_int);
00157 sprintf(val, "%d\0", x_int);
00158 break;
00159
00160 case LONG:
00161 long x_long;
00162 RecvVariable(keyword, &x_long);
00163 sprintf(val, "%ld\0", x_long);
00164 break;
00165
00166 case FLOAT:
00167 float x_float;
00168 RecvVariable(keyword, &x_float);
00169 sprintf(val, "%g\0", x_float);
00170 break;
00171
00172 case DOUBLE:
00173 double x_double;
00174 RecvVariable(keyword, &x_double);
00175 sprintf(val, "%g\0", x_double);
00176 break;
00177
00178 default:
00179 strcpy(val, "error");
00180 break;
00181 }
00182
00183 return val;
00184 }
00185
00186 int DataClient::SendValue(char *keyword, char *value)
00187 {
00188 int handle = keytable->getKeyHandle(keyword);
00189
00190 if (handle == keytable->n)
00191 {
00192 cout << "Error: Keyword \"" << keyword << "\" not found!" << endl << flush;
00193 return POSSE_INVALID_KEY;
00194 }
00195
00196 if (!keytable->isViewableVar(handle))
00197 {
00198 cout << "Error: Keyword \"" << keyword << "\" not a valid Variable!" << endl << flush;
00199 return POSSE_INVALID_VARIABLE;
00200 }
00201
00202 if (!isWritable(keytable->key[handle].key))
00203 {
00204 return POSSE_READONLY_KEY;
00205 }
00206
00207 switch (keytable->key[handle].vartype)
00208 {
00209 case CHAR:
00210 if (keytable->isCharArray(handle))
00211 {
00212 SendArray(keyword, value);
00213 }
00214 else
00215 {
00216 char x_char;
00217 sscanf(value, "%c", &x_char);
00218 SendVariable(keyword, x_char);
00219 }
00220 break;
00221
00222
00223 case SHORT:
00224 short x_short;
00225 sscanf(value, "%d", &x_short);
00226 SendVariable(keyword, x_short);
00227 break;
00228
00229 case INT:
00230 int x_int;
00231 sscanf(value, "%d", &x_int);
00232 SendVariable(keyword, x_int);
00233 break;
00234
00235 case LONG:
00236 long x_long;
00237 sscanf(value, "%ld", &x_long);
00238 SendVariable(keyword, x_long);
00239 break;
00240
00241 case FLOAT:
00242 float x_float;
00243 sscanf(value, "%f", &x_float);
00244 SendVariable(keyword, x_float);
00245 break;
00246
00247 case DOUBLE:
00248 double x_double;
00249 sscanf(value, "%lf", &x_double);
00250 SendVariable(keyword, x_double);
00251 break;
00252
00253 default:
00254 cout << "Error: Undefined type for keyword \"" << keyword << "\"!!" << endl << flush;
00255 return -3;
00256 break;
00257 }
00258
00259 return POSSE_SUCCESS;
00260 }
00261
00262 void DataClient::ListKeywords()
00263 {
00264 keytable->List();
00265 }
00266
00267 void DataClient::ListValues()
00268 {
00269 RecvKeyTable(keytable);
00270 keytable->ListValues();
00271 }
00272
00273 KeyTable *DataClient::GetTable()
00274 {
00275 return keytable;
00276 }
00277
00278 bool DataClient::isValidKeyword(char *keyword, int *handle)
00279 {
00280 #ifdef ANIDEBUG
00281 cout << "DataClient::isValidKeyword: Checking for validity of keyword \"" << keyword << "\"." << endl << flush;
00282 #endif
00283 int i = keytable->getKeyHandle(keyword);
00284 if (handle)
00285 *handle = i;
00286 if (i == keytable->n)
00287 {
00288 cout << "Error!! Server does not identify keyword \"" << keyword << "\"!!" << endl << flush;
00289 return false;
00290 }
00291 return true;
00292 }
00293
00294 bool DataClient::isWritable(int handle)
00295 {
00296 if (!keytable->isWritable(handle))
00297 {
00298 cout << "Error!! Data for keyword \"" << keytable->key[handle].key << "\" cannot be modified. ";
00299 cout << "It is marked READ-ONLY by the server!" << endl << flush;
00300 return false;
00301 }
00302 return true;
00303 }
00304
00305 bool DataClient::isWritable(char *keyword)
00306 {
00307 int handle = keytable->getKeyHandle(keyword);
00308 if (handle < keytable->n)
00309 return isWritable(handle);
00310 return false;
00311 }
00312
00313 bool DataClient::isVariable(int handle)
00314 {
00315 int size = keytable->key[handle].elem_size;
00316 if (!keytable->isVar(handle))
00317 {
00318 cout << "Error!! Incompatible data types for keyword \"" << keytable->key[handle].key << "\"!!" << endl;
00319 cout << "\tServer expects a \"" << keytable->key[handle].description << "\" of type \"" << keytable->key[handle].type << "\"." << endl;
00320 cout << "\tClient expects a \"Variable\"!!" << endl << flush;
00321 return false;
00322 }
00323 return true;
00324 }
00325
00326 bool DataClient::VerifyElementSize(int handle, int elem_size)
00327 {
00328 int size = keytable->key[handle].elem_size;
00329 if (size != elem_size)
00330 {
00331 cout << "Error!! Incompatible element type for keyword \"" << keytable->key[handle].key << "\"!!" << endl;
00332 cout << "\tServer expects element of type \"" << keytable->key[handle].type << "\" [" << size << " bytes]." << endl;
00333 cout << "\tClient expects element of size " << elem_size << " bytes!!" << endl << flush;
00334 return false;
00335 }
00336 return true;
00337 }
00338
00339 bool DataClient::SendKeyword(char *keyword)
00340 {
00341 #ifdef ANIDEBUG
00342 cout << "DataClient::SendKeyword: Sending keyword \"" << keyword << "\"." << e
00343 ndl << flush;
00344 #endif
00345
00346 SendLine(keyword);
00347
00348 return true;
00349 }
00350
00351 bool DataClient::SendKeyForDataSend(int handle)
00352 {
00353 #ifdef ANIDEBUG
00354 cout << "DataClient::SendKeyForDataSend: Sending key \"" << keytable->key[handle].key << "\" to server." << endl << flush;
00355 #endif
00356 if (!isWritable(handle)) return false;
00357
00358 char key[100];
00359 key[0] = 'R';
00360 strcpy(&key[1], keytable->key[handle].key);
00361 SendLine(key);
00362
00363 return true;
00364 }
00365
00366 bool DataClient::SendKeyForDataSend(char *keyword)
00367 {
00368 int handle = keytable->getKeyHandle(keyword);
00369 if (handle < keytable->n)
00370 return SendKeyForDataSend(handle);
00371 return false;
00372 }
00373
00374 int DataClient::RecvDummyBytes(int size)
00375 {
00376 cout << endl;
00377 cout << "Receiving " << size << " bytes of dummy data before exiting." << endl;
00378 cout << flush;
00379
00380 unsigned char *data;
00381 ALLOC1D(&data, size);
00382 RecvBytes(size, data);
00383 FREE1D(&data, size);
00384
00385 Release();
00386 return 0;
00387 }
00388
00389 bool DataClient::isBigEndian()
00390 {
00391 int size = QueryKeyword("_isBigEndian");
00392 int val = RecvVar<int>();
00393 return (val == 1);
00394 }
00395
00396 int DataClient::SendClientName()
00397 {
00398 char hostname[200];
00399 gethostname(hostname,200);
00400 SendLine(hostname);
00401
00402 return 0;
00403 }
00404
00405 bool DataClient::isDynamicArray(int handle, int dim)
00406 {
00407 bool result = (keytable->key[handle].description == DYNAMIC_1D_ARRAY+dim-1);
00408
00409 if (!result)
00410 {
00411 cout << "Error!! Incompatible data type for keyword \"" << keytable->key[handle].key << "\"!!" << endl;
00412 cout << "\tServer expects a \"" << keytable->Description(handle) << "\" of type \"" << keytable->key[handle].type << "\"." << endl;
00413 cout << "\tClient expects a \"Dynamic " << dim << "D Array\"!!" << endl << flush;
00414 }
00415 return result;
00416 }
00417
00418 int DataClient::getArrayDim(char *keyword, int dim)
00419 {
00420 int handle;
00421 int err = ERR_BAD_DATA;
00422 if (!isValidKeyword(keyword, &handle)) throw err;
00423 if (!strstr(keytable->Description(handle), "Dynamic"))
00424 {
00425 cout << "DataClient::getArrayDim: Error!!" << endl;
00426 cout << "\t\"" << keyword << "\" is non-dynamic array!!" << endl << flush;
00427 exit(-1);
00428 throw err;
00429 }
00430 int ndims = keytable->key[handle].description-DYNAMIC_1D_ARRAY+1;;
00431
00432 if (dim > ndims)
00433 {
00434 cout << "DataClient::getArrayDim: Error!!" << endl;
00435 cout << "\tDimension " << dim << " requested for a " << ndims << "D array!" << endl << flush;
00436 throw err;
00437 }
00438
00439 char key[100];
00440 sprintf(key, "%s_dim%d", keyword, dim);
00441
00442 return RecvVariable<int>(key);
00443 }
00444