00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #include "soapH.h"
00028 #include "acq2xx.nsmap"
00029
00030 #ifdef __arm
00031 #include "local.h"
00032 #else
00033 #include <stdio.h>
00034 #endif
00035
00036 #ifndef __arm
00037 #define info printf
00038 #endif
00039 #define MAXBUF 16384
00040
00041 using namespace std;
00042
00043 #include <assert.h>
00044 #include <iostream>
00045 #include <iomanip>
00046 #include <string>
00047
00048 #define ACQCMD "/usr/local/bin/acqcmd"
00049
00050 #define NOT_FOR_SERVER 0
00051
00052 static int verbose = 0;
00053 static int logcommands = 0;
00054
00055 #include <string.h>
00056
00057
00058 class Actor {
00059 public:
00060 virtual ~Actor() {}
00061 virtual int spawn_read(char* lcommand, char* buf, int maxbuf);
00062 };
00063
00064 class ActorStub : public Actor {
00065 public:
00066 virtual int spawn_read(char* lcommand, char* buf, int maxbuf);
00067 };
00068
00069
00070 static Actor* actor = new Actor();
00071
00072
00073 #include "soapH.h"
00074 #include <pthread.h>
00075 #define BACKLOG (100) // Max. request backlog
00076 #define MAX_THR (10) // Max. threads to serve requests
00077
00078 static int cgi_main(soap* soap);
00079 static int standalone_main(soap* soap, int port);
00080
00081 int main(int argc, char **argv)
00082 {
00083 struct soap soap;
00084 soap_init(&soap);
00085
00086 #ifdef __arm
00087 info("acq2xx_server $Revision: 1.23 $ " ACQ2XX_H_VERSION);
00088 #endif
00089 if (getenv("ACQ2XX_SERVER_STUB")){
00090 actor = new ActorStub();
00091 }
00092 if (getenv("ACQ2XX_LOG")){
00093 logcommands = atoi(getenv("ACQ2XX_LOG"));
00094 info("ACQ2XX_LOG set logcommands %d", logcommands);
00095 }
00096 if (getenv("ACQ2XX_WS_VERBOSE")){
00097 verbose = atoi(getenv("ACQ2XX_WS_VERBOSE"));
00098 info("ACQ2XX_WS_VERBOSE set verbose %d", verbose);
00099 }
00100
00101
00102 if (argc < 2){
00103 return cgi_main(&soap);
00104 }else{
00105 return standalone_main(&soap, atoi(argv[1]));
00106 }
00107 }
00108
00109
00110 static int cgi_main(soap* soap)
00111 {
00112 soap_serve(soap);
00113 soap_destroy(soap);
00114 soap_end(soap);
00115 return 0;
00116 }
00117
00118 static void print_signon(soap* soap, int i, int s)
00119 {
00120 #ifdef __arm
00121 info(
00122 #else
00123 fprintf(stderr,
00124 #endif
00125 "Thread %d accepts socket %d connection from IP %d.%d.%d.%d\n",
00126 i, s, (soap->ip >> 24)&0xFF, (soap->ip >> 16)&0xFF,
00127 (soap->ip >> 8)&0xFF, soap->ip&0xFF);
00128 }
00129
00130
00131 static int standalone_main(soap* soap, int port)
00132 {
00133
00134 struct soap *soap_thr[MAX_THR];
00135 pthread_t tid[MAX_THR];
00136 SOAP_SOCKET m, s;
00137 int i;
00138
00139 m = soap_bind(soap, NULL, port, BACKLOG);
00140 if (!soap_valid_socket(m)){
00141 exit(1);
00142 }
00143 fprintf(stderr, "Socket connection successful %d\n", m);
00144 for (i = 0; i < MAX_THR; i++){
00145 soap_thr[i] = NULL;
00146 }
00147 for (;;){
00148 for (i = 0; i < MAX_THR; i++){
00149 s = soap_accept(soap);
00150 if (!soap_valid_socket(s)){
00151 if (soap->errnum){
00152 soap_print_fault(soap, stderr);
00153 continue;
00154 }else{
00155 #ifdef __arm
00156 err(
00157 #else
00158 fprintf(stderr,
00159 #endif
00160 "Server timed out\n");
00161 break;
00162 }
00163 }
00164 print_signon(soap, i, s);
00165
00166 if (!soap_thr[i]){
00167 soap_thr[i] = soap_copy(soap);
00168 if (!soap_thr[i]){
00169 exit(1);
00170 }
00171 }else{
00172 pthread_join(tid[i], NULL);
00173 #ifdef __arm
00174 info(
00175 #else
00176 fprintf(stderr,
00177 #endif
00178 "Thread %d completed\n", i);
00179
00180 soap_destroy(soap_thr[i]);
00181
00182 soap_end(soap_thr[i]);
00183 }
00184 soap_thr[i]->socket = s;
00185 pthread_create(
00186 &tid[i], NULL, (void*(*)(void*))soap_serve,
00187 (void*)soap_thr[i]);
00188 }
00189 }
00190 for (i = 0; i < MAX_THR; i++){
00191 if (soap_thr[i]){
00192 soap_done(soap_thr[i]);
00193 free(soap_thr[i]);
00194 }
00195 }
00196
00197 return 0;
00198 }
00199
00200
00201 int Actor::spawn_read(char* lcommand, char* buf, int maxbuf)
00202 {
00203 if (logcommands){
00204 info("cmd:%s", lcommand);
00205 }
00206 FILE* fp = popen(lcommand, "r");
00207
00208 buf[0] = '\0';
00209
00210 for (char* bp = buf; bp - buf < MAXBUF; ){
00211 char *nl = fgets(bp, 256, fp);
00212 if (nl){
00213 bp += strlen(nl);
00214 }else{
00215 break;
00216 }
00217 }
00218 int rc = pclose(fp);
00219
00220 if (logcommands > 1){
00221 info("[%d] %s", rc, buf);
00222 }
00223
00224 return rc;
00225 }
00226
00227 int ActorStub::spawn_read(char* lcommand, char* buf, int maxbuf)
00228 {
00229 char *stubcommand = new char[strlen(lcommand)+10];
00230
00231 cout << lcommand << endl;
00232
00233 sprintf(stubcommand, "echo %s", lcommand);
00234 return Actor::spawn_read(stubcommand, buf, maxbuf);
00235 }
00236
00237
00238 static int soap_command(
00239 struct soap* soap, char* lcommand, char* command, char*& response)
00240 {
00241 char* buf = (char*)soap_malloc(soap, MAXBUF);
00242
00243 sprintf(buf, "%s \'%s\'", lcommand, command);
00244
00245 actor->spawn_read(buf, buf, MAXBUF);
00246
00247 response = buf;
00248 return SOAP_OK;
00249 }
00250
00251
00252 int acq2xx__acqcmd(struct soap *soap, char* command, char*& response)
00253 {
00254 return soap_command(soap, ACQCMD, command, response);
00255 }
00256
00257 int acq2xx__acq2sh(struct soap *soap, char* command, char*& response)
00258 {
00259 return soap_command(soap, "sh -c", command, response);
00260 }
00261
00262 int acq2xx__getVersion(
00263 struct soap *soap,
00264 char* client_version,
00265 char*& server_version)
00266 {
00267 char* buf = (char*)soap_malloc(soap, strlen(ACQ2XX_H_VERSION)+1);
00268
00269 strcpy(buf, ACQ2XX_H_VERSION);
00270 server_version = buf;
00271
00272 if (strcmp(client_version, server_version) != 0){
00273 info("WARNING: version mismatch client: %s server %s",
00274 client_version, server_version);
00275 }
00276
00277 return SOAP_OK;
00278 }
00279
00280 static int acqcmd(const char* command, char* buf, int maxbuf)
00281 {
00282 char lcommand[128];
00283
00284 sprintf(lcommand, "%s \'%s\'", ACQCMD, command);
00285 actor->spawn_read(lcommand, buf, maxbuf);
00286 return 0;
00287 }
00288
00289 int acq2xx__getAcqStatus(struct soap *soap, struct acq2xx__AcqStatus& status)
00290 {
00291 char buf[256];
00292 acq2xx__AcqStatus lbuf;
00293 char* state_string = (char*)soap_malloc(soap, 32);
00294 lbuf.nchan = 5;
00295 lbuf.state_string = "Hello World";
00296
00297 acqcmd("getNumSamples", buf, 256);
00298 sscanf(buf, "ACQ32:getNumSamples=%d pre=%d post=%d elapsed=%d",
00299 &lbuf.numsamples, &lbuf.prelen,
00300 &lbuf.postlen, &lbuf.elapsed);
00301
00302 acqcmd("getState", buf, 256);
00303 sscanf(buf, "ACQ32:%d %s", &lbuf.state, state_string);
00304 lbuf.state_string = state_string;
00305
00306 acqcmd("getNumChannels", buf, 256);
00307 sscanf(buf, "ACQ32:getNumChannels=%d", &lbuf.nchan);
00308 status = lbuf;
00309
00310
00311 return SOAP_OK;
00312 }
00313
00314
00315 int acq2xx__setArm(
00316 struct soap* soap,
00317 int block,
00318 struct acq2xx__AcqStatus& status)
00319 {
00320 char buf[256];
00321
00322 acqcmd("setArm", buf, 256);
00323
00324 if (block){
00325 acq2xx__AcqStatus lbuf;
00326 int scanned;
00327
00328 do{
00329 acqcmd("getState", buf, 256);
00330 scanned = sscanf(buf, "ACQ32:%d", &lbuf.state);
00331 } while(scanned == 1 && lbuf.state != ST_STOP);
00332
00333 }
00334
00335 return acq2xx__getAcqStatus(soap, status);
00336 }
00337
00338
00339 int acq2xx__waitStop(
00340 struct soap* soap,
00341 int timeout_sec,
00342 struct acq2xx__AcqStatus& status)
00343 {
00344 if (timeout_sec < 1) timeout_sec = 1;
00345 if (timeout_sec > 10) timeout_sec = 10;
00346
00347 char command[80];
00348 char buf[80];
00349 buf[0] = '\0';
00350
00351 sprintf(command, "acqcmd -t %d --until ST_STOP", timeout_sec);
00352
00353 actor->spawn_read(command, buf, 80);
00354 return acq2xx__getAcqStatus(soap, status);
00355 }
00356
00357
00358 static const char* toString(enum acq2xx__DIx dix)
00359 {
00360 switch(dix){
00361 case DI0:
00362 return "DI0";
00363 case DI1:
00364 return "DI1";
00365 case DI2:
00366 return "DI2";
00367 case DI3:
00368 return "DI3";
00369 case DI4:
00370 return "DI4";
00371 case DI5:
00372 return "DI5";
00373 case DI_NONE:
00374 default:
00375 return "none";
00376 }
00377 }
00378
00379 static const char* toString(enum acq2xx__DOx dox)
00380 {
00381 switch(dox){
00382 case DO0:
00383 return "DO0";
00384 case DO1:
00385 return "DO1";
00386 case DO2:
00387 return "DO2";
00388 case DO3:
00389 return "DO3";
00390 case DO4:
00391 return "DO4";
00392 case DO5:
00393 return "DO5";
00394 case DO_NONE:
00395 default:
00396 return "none";
00397 }
00398 }
00399
00400 static const char* toString(enum acq2xx__EDGE edge){
00401 return edge==EDGE_FALLING? "falling": "rising";
00402 }
00403
00404
00405
00406 int acq2xx__acq2script(
00407 struct soap* soap,
00408 acq2xx__Transaction *in,
00409 struct acq2xx__acq2scriptResponse &result)
00410 {
00411 if (in == 0){
00412 cerr << "ERROR: null transaction" << endl;
00413 return -1;
00414 }
00415
00416 in->exec(soap);
00417 result.out = in;
00418 if (verbose){
00419 cout << "acq2xx__acq2script" << " output: "; result.out->print();
00420 }
00421 return SOAP_OK;
00422 }
00423
00424
00425
00426 void acq2xx__Transaction::exec(soap *soap)
00427 {
00428 status = run(soap);
00429 complete = 1;
00430
00431 if (verbose > 1){
00432 cout << "exec() done complete: " << complete
00433 << "status: " <<status ; print();
00434 }
00435 }
00436
00437 int acq2xx__Transaction::run(soap *soap)
00438 {
00439 cout << "Transaction::run"; print();
00440 return 37;
00441 }
00442
00443
00444
00445
00446 int acq2xx__TransactionList::run(soap *soap)
00447 {
00448 for (int i = 0; i < __size; i++){
00449 acq2xx__Transaction* t = __ptr[i];
00450
00451 t->exec(soap);
00452 if (t->status != 0 && t->abort_on_error){
00453 return t->status;
00454 }
00455 }
00456
00457 return 0;
00458 }
00459
00460
00461
00462
00463 int acq2xx__ShellTransaction::run(soap *soap)
00464 {
00465
00466 char* buf = (char*)malloc(MAXBUF);
00467 buf[0] = '\0';
00468 int rc = actor->spawn_read(command, buf, MAXBUF);
00469
00470 char *_result = (char*)soap_malloc(soap, strlen(buf)+1);
00471 strcpy(_result, buf);
00472 result = _result;
00473
00474 if (verbose > 1){
00475 cout << "acq2xx__ShellTransaction::run() command:" << command << endl <<
00476 "result:" << result << " rc:" << rc << endl;
00477 }
00478
00479 free(buf);
00480 return rc;
00481 }
00482
00483
00484 acq2xx__ModeSetTransaction::acq2xx__ModeSetTransaction(
00485 enum acq2xx__MODE mode,
00486 int prelen,
00487 int postlen
00488 )
00489 {
00490 assert(NOT_FOR_SERVER);
00491 }
00492
00493 int acq2xx__ModeSetTransaction::run(struct soap* soap)
00494 {
00495 char _command[80];
00496
00497 cout <<
00498 "acq2xx__ModeSetTransaction::run() "<< endl <<
00499 "mode:" << mode << " pre:" << prelen <<
00500 " post:" << postlen << endl;
00501
00502 switch(mode){
00503 case MODE_SOFT_TRANSIENT:
00504 case MODE_SOFT_CONTINUOUS:
00505 sprintf(_command, "acqcmd setMode %s %d",
00506 mode==MODE_SOFT_TRANSIENT?
00507 "SOFT_TRANSIENT": "SOFT_CONTINUOUS",
00508 mode==MODE_SOFT_TRANSIENT? postlen: prelen);
00509 break;
00510 case MODE_GATED_TRANSIENT:
00511 sprintf(_command, "acqcmd setMode GATED_TRANSIENT %d",
00512 postlen);
00513 break;
00514 case MODE_TRIGGERED_CONTINUOUS:
00515 sprintf(_command, "acqcmd setModeTriggeredContinuous %d %d",
00516 prelen, postlen);
00517 break;
00518 default:
00519 assert(0);
00520 }
00521
00522
00523 initCommand(_command);
00524
00525 if (verbose > 1){
00526 cout << "acq2xx__ModeSetTransaction::run() "<<
00527 _command << endl <<
00528 "command:" << command << endl;
00529 }
00530
00531 return acq2xx__ShellTransaction::run(soap);
00532 }
00533
00534
00535 acq2xx__ClockSetTransaction::acq2xx__ClockSetTransaction(char *command) :
00536 acq2xx__ShellTransaction(command)
00537 {
00538 assert(NOT_FOR_SERVER);
00539 }
00540
00541 acq2xx__InternalClockSetTransaction::acq2xx__InternalClockSetTransaction(
00542 int _hz,
00543 int div,
00544 enum acq2xx__DOx dox)
00545 {
00546 assert(NOT_FOR_SERVER);
00547 }
00548
00549 int acq2xx__InternalClockSetTransaction::run(struct soap* soap)
00550 {
00551 char _command[80];
00552 int cursor = sprintf(_command, "acqcmd setInternalClock %d", hz);
00553 if (div > 1 || dox != DO_NONE){
00554 cursor += sprintf(_command+cursor, " %d", div);
00555
00556 if (dox != DO_NONE){
00557 cursor += sprintf(_command+cursor, " %s",
00558 toString(dox));
00559 }
00560 }
00561 initCommand(_command);
00562 return acq2xx__ClockSetTransaction::run(soap);
00563 }
00564
00565 acq2xx__ExternalClockSetTransaction::acq2xx__ExternalClockSetTransaction(
00566 enum acq2xx__DIx dix,
00567 int div,
00568 enum acq2xx__DOx dox
00569 )
00570 {
00571 assert(NOT_FOR_SERVER);
00572 }
00573
00574 int acq2xx__ExternalClockSetTransaction::run(struct soap* soap)
00575 {
00576 char _command[80];
00577
00578 int cursor = sprintf(_command, "acqcmd setExternalClock %s",
00579 toString(dix));
00580 if (div > 1 || dox != DO_NONE){
00581 cursor += sprintf(_command+cursor, " %d", div);
00582
00583 if (dox != DO_NONE){
00584 cursor += sprintf(_command+cursor, " %s",
00585 toString(dox));
00586 }
00587 }
00588 initCommand(_command);
00589 return acq2xx__ClockSetTransaction::run(soap);
00590 }
00591
00592 acq2xx__SignalSetTransaction::acq2xx__SignalSetTransaction(
00593 char *name,
00594 enum acq2xx__DIx dix,
00595 enum acq2xx__EDGE edge)
00596 {
00597 assert(NOT_FOR_SERVER);
00598 }
00599
00600 int acq2xx__SignalSetTransaction::run(soap* soap)
00601 {
00602 char command[80];
00603 sprintf(command, "set.%s %s %s", signal,
00604 toString(dix), dix != DI_NONE? toString(edge): "");
00605 initCommand(command);
00606 return acq2xx__ShellTransaction::run(soap);
00607 }
00608
00609 acq2xx__AcqControlTransaction::acq2xx__AcqControlTransaction(
00610 acq2xx__ModeSetTransaction* _modeSet,
00611 acq2xx__ClockSetTransaction* _clockSet,
00612 acq2xx__SignalSetTransaction* _trigger,
00613 acq2xx__SignalSetTransaction* _event0
00614 )
00615 {
00616 assert(NOT_FOR_SERVER);
00617 }
00618
00619 acq2xx__AcqControlTransaction::acq2xx__AcqControlTransaction()
00620 {
00621 }
00622
00623 int acq2xx__GetAvailableChannelsTransaction::run(soap* soap)
00624 {
00625 int rc = acq2xx__ShellTransaction::run(soap);
00626 if (rc == 0){
00627 return sscanf(result,
00628 "ACQ32:getAvailableChannels AI=%d AO=%d",
00629 &AI, &AO) != 2;
00630 }else{
00631 return rc;
00632 }
00633 }
00634
00635
00636 static int parseVR(VRange* ranges, int channels, char* result)
00637 {
00638 char *rbuf = (char*)malloc(strlen(result)+1);
00639
00640 strcpy(rbuf, result);
00641 char *str = rbuf;
00642 char *tok;
00643
00644 for (int ic = 0; ic < channels; ++ic){
00645 if ((tok = strtok(str, ","))){
00646 ranges[ic].min = atof(tok);
00647 }else{
00648 return -1;
00649 }
00650 str = 0;
00651 if ((tok = strtok(str, ","))){
00652 ranges[ic].max = atof(tok);
00653 }else{
00654 return -1;
00655 }
00656 }
00657 free(rbuf);
00658 return 0;
00659 }
00660 int acq2xx__GetVRangeTransaction::run(soap* soap)
00661 {
00662 channels = soap_new_acq2xx__GetAvailableChannelsTransaction(soap, -1);
00663
00664 int rc = channels->run(soap);
00665 if (rc == 0){
00666 rc = acq2xx__ShellTransaction::run(soap);
00667 if (rc == 0){
00668 ranges.__ptr = soap_new_VRange(soap, channels->AI);
00669 ranges.__size = channels->AI;
00670 return parseVR(ranges.__ptr, channels->AI, result);
00671 }
00672 }
00673
00674 return rc;
00675 }