Back to home page

sPhenix code displayed by LXR

 
 

    


File indexing completed on 2025-08-02 08:21:07

0001 
0002 #include "mongoose.h"
0003 #include "rcdaq.h"
0004 
0005 #include <iostream>
0006 #include <sstream>
0007 #include <sys/stat.h>
0008 
0009 using namespace std;
0010 
0011 int update(struct mg_connection *nc, const char *key, const double value);
0012 int update(struct mg_connection *nc, const char *key, const int value);
0013 int update(struct mg_connection *nc, const char *key, const char *value);
0014 int trigger_updates(struct mg_connection *nc);
0015 
0016 void initial_ws_update (struct mg_connection *nc);
0017 void send_ws_updates (struct mg_connection *nc);
0018 void send_updates (struct mg_connection *nc);
0019 void send_status (struct mg_connection *nc, std::string out);
0020 void send_error (struct mg_connection *nc, std::string out);
0021 void send_nothing (struct mg_connection *nc);
0022 void * mg_server (void *arg);
0023 
0024 static void broadcast(struct mg_connection *nc, char *str, const int len);
0025 
0026 
0027 static struct mg_serve_http_opts s_http_server_opts;
0028 
0029 int end_web_thread = 0;
0030 
0031 pthread_mutex_t M_ws_send;
0032 
0033 int error_flag = 0;
0034 std::string error_string = "";
0035 
0036 static int  last_runstate;
0037 static int  last_runnumber;
0038 static int  last_eventnumber;
0039 static double  last_runvolume;
0040 static int  last_runduration;
0041 static int  last_openflag;
0042 static int  last_serverflag;
0043 static int  rcdaqname_request_flag; 
0044 static int  speed_request_flag = 0; 
0045 
0046 static int speed_update_interval =9;
0047 
0048 
0049 
0050 int mg_end()
0051 {
0052   end_web_thread = 1;
0053   return 0;
0054 }
0055 
0056 int request_mg_update (const int what)
0057 {
0058   switch (what)
0059     {
0060     case MG_REQUEST_NAME:
0061       rcdaqname_request_flag = 1;
0062       return 0;
0063       break;
0064 
0065     case MG_REQUEST_SPEED:
0066       speed_request_flag = 1;
0067       return 0;
0068       break;
0069       
0070     default:
0071       break;
0072     }
0073   return -1;
0074 }
0075 
0076 
0077 // static int is_websocket(const struct mg_connection *nc)
0078 // {
0079 //   return nc->flags & MG_F_IS_WEBSOCKET;
0080 // }
0081 
0082 std::string get_statusstring()
0083 {
0084   stringstream out;
0085 
0086   if ( error_flag)
0087     {
0088       return  error_string;
0089     }
0090   else if ( daq_running() )
0091     {
0092       out << "Running for " << get_runduration() << "s" << ends;
0093     }
0094   else
0095     {
0096       out << "Stopped Run " << get_oldrunnumber() << ends;
0097     }
0098   return out.str();
0099 }
0100 
0101 std::string get_loggingstring()
0102 {
0103   stringstream out;
0104   if ( get_openflag())
0105     {
0106       if ( daq_running() )
0107     {
0108       if ( get_serverflag() )
0109         {
0110           out << "File on server: " << get_current_filename();
0111           return out.str();
0112         }
0113       else
0114         {
0115           out << "File: " << get_current_filename();
0116           return out.str();
0117         }
0118     }
0119       else
0120     {
0121       if ( get_serverflag() )
0122         {
0123           return "Logging enabled (Server)";
0124         }
0125       else
0126         {
0127           return "Logging enabled";
0128         }
0129     }
0130     }
0131   return "Logging disabled";
0132 }
0133 
0134 
0135 void initial_ws_update (struct mg_connection *nc)
0136 {
0137   char str[2048];
0138   int len;
0139   
0140   int openvalue = get_openflag() | get_serverflag();
0141   
0142   len = sprintf(str, "{ \"RunFlag\":%d, \"Status\":\"%s\" , \"RunNr\":%d , \"Events\":%d , \"Volume\":\"%f\", \"Duration\":%d, \"Logging\":\"%s\" ,\"Filename\":\"%s \" , \"OpenFlag\":%d , \"Name\":\"%s\"  } "
0143         , daq_running()
0144         , get_statusstring().c_str()
0145         , get_runnumber()
0146         , get_eventnumber()
0147         , get_runvolume()
0148         , get_runduration()
0149         , get_loggingstring().c_str()
0150         , get_current_filename().c_str()
0151         , openvalue
0152         , daq_get_myname().c_str()
0153         );
0154   //  cout << __FILE__ << " " << __LINE__ << " " << str << endl;
0155 
0156   mg_send_websocket_frame(nc, WEBSOCKET_OP_TEXT, str, len);
0157 //  broadcast(nc, str, len);
0158   
0159 }
0160 
0161 static void broadcast(struct mg_connection *nc, char *str, const int len)
0162 {
0163   struct mg_connection *c;
0164 
0165   for (c = mg_next(nc->mgr, NULL); c != NULL; c = mg_next(nc->mgr, c))
0166     {
0167       if ( c != nc)
0168     {
0169       // cout << __FILE__ << " " << __LINE__ << " sending " << str << " to " << c << endl;
0170 
0171       //       pthread_mutex_lock(&M_ws_send); 
0172       mg_send_websocket_frame(c, WEBSOCKET_OP_TEXT, str, len);
0173       //pthread_mutex_unlock(&M_ws_send); 
0174     }
0175     }
0176 }
0177 
0178 
0179 int update(struct mg_connection *nc, const char *key, const double value)
0180 {
0181   char str[512];
0182   int len = sprintf(str, "{ \"%s\":%f }", key, value);
0183 
0184   broadcast(nc, str, len);
0185   return 0;
0186 }
0187 
0188 int update(struct mg_connection *nc, const char *key, const int value)
0189 {
0190   char str[512];
0191   int len = sprintf(str, "{ \"%s\":%d }", key, value);
0192 
0193   broadcast(nc, str, len);
0194   return 0;
0195 }
0196   
0197 int update(struct mg_connection *nc, const char *key, const char *value)
0198 {
0199   char str[512];
0200   int len = sprintf(str, "{ \"%s\":\"%s\" }", key, value);
0201 
0202   broadcast(nc, str, len);
0203   return 0;
0204 }
0205   
0206 void send_ws_updates (struct mg_connection *nc)
0207 {
0208   if ( daq_running() )
0209     {
0210       //      cout << __FILE__ << " " << __LINE__ << " in send_ws_updates" << endl;
0211       update(nc, "Volume", get_runvolume());
0212       update(nc, "Events", get_eventnumber());
0213       update(nc, "Status", get_statusstring().c_str() );
0214     }
0215 
0216 }
0217 
0218 void send_updates (struct mg_connection *nc)
0219 {
0220   char str[512];
0221   int len;
0222 
0223   
0224   len = sprintf(str, "{ \"Events\":%d , \"Volume\":\"%f\" , \"Status\":\"%s\"  }"
0225         , get_eventnumber()
0226         , get_runvolume()
0227         , get_statusstring().c_str()
0228         );
0229 
0230   //cout << __FILE__ << " " << __LINE__ << " sending " << str << endl;
0231   nc->flags |= MG_F_SEND_AND_CLOSE;
0232   mg_printf(nc, "HTTP/1.0 200 OK\r\nContent-Length: %d\r\n"
0233         "Content-Type: application/json\r\n\r\n%s",
0234         len, str);
0235   
0236 }
0237 
0238 void send_status (struct mg_connection *nc, std::string out)
0239 {
0240 
0241   // we eliminate the line break
0242   ostringstream x;
0243   x<< endl;
0244   
0245   out.replace(out.find(x.str()),x.str().length(),"");
0246   //cout << __FILE__ << " " << __LINE__ << " " << out << endl;
0247 
0248 
0249   
0250   char str[512];
0251   int len;
0252   len = sprintf(str, "{ \"Status\":\"%s\" }"
0253         , out.c_str() );
0254 
0255   //  pthread_mutex_lock(&M_ws_send); 
0256   nc->flags |= MG_F_SEND_AND_CLOSE;
0257   mg_printf(nc, "HTTP/1.0 200 OK\r\nContent-Length: %d\r\n"
0258         "Content-Type: application/json\r\n\r\n%s",
0259         len, str);
0260   // pthread_mutex_unlock(&M_ws_send); 
0261   
0262 }
0263 
0264 void send_error (struct mg_connection *nc, std::string out)
0265 {
0266 
0267   // we eliminate the line break
0268   ostringstream x;
0269   x<< endl;
0270   
0271   out.replace(out.find(x.str()),x.str().length(),"");
0272   //cout << __FILE__ << " " << __LINE__ << " " << out << endl;
0273 
0274 
0275   
0276   //  pthread_mutex_lock(&M_ws_send); 
0277   nc->flags |= MG_F_SEND_AND_CLOSE;
0278   mg_printf(nc, "{ \"Status\":\"%s\" }", out.c_str());
0279   // pthread_mutex_unlock(&M_ws_send); 
0280   
0281 }
0282 
0283 void send_nothing (struct mg_connection *nc)
0284 {
0285   //  pthread_mutex_lock(&M_ws_send); 
0286   //  printf(" sending HTTP/1.0 200 OK\r\nContent-Length: 0\r\nContent-Type: text/html\r\n\r\n");
0287   nc->flags |= MG_F_SEND_AND_CLOSE;
0288   mg_printf(nc, "HTTP/1.0 200 OK\r\nContent-Length: 0\r\n"
0289         "Content-Type: text/html\r\n\r\n");
0290   //pthread_mutex_unlock(&M_ws_send); 
0291   
0292 }
0293 
0294 
0295 
0296 //int has_request=0;
0297 
0298 static void ev_handler(struct mg_connection *nc, int ev, void *ev_data)
0299 {
0300   struct http_message *hm = (struct http_message *) ev_data;
0301   struct websocket_message *wm = (struct websocket_message *)ev_data;
0302   int status;
0303    
0304   std::ostringstream out;
0305          
0306   //   if (ev)  printf (" ----   %d\n" ,ev);
0307   //   printf (" --bit 20 --   %lx\n" , nc->flags & MG_F_USER_1);
0308   switch (ev)
0309     {
0310     case MG_EV_WEBSOCKET_HANDSHAKE_DONE:
0311       {
0312     /* New websocket connection. Tell everybody. */
0313     nc->flags |=  MG_F_USER_1;
0314     break;
0315       }
0316 
0317     case MG_EV_WEBSOCKET_FRAME:
0318       {
0319     struct mg_str msg = {(char *) wm->data, wm->size};
0320     //cout << __FILE__ << " " << __LINE__ << " ws message " << wm->data << endl;
0321      
0322     if ( mg_vcmp ( &msg, "daq_begin") == 0)
0323       {
0324          
0325         status = daq_begin(0,out);
0326         if (status)
0327           {
0328         error_flag = 1;
0329         error_string = out.str();
0330         error_string.replace(error_string.find("\n"),1,"");
0331 
0332           }
0333         else
0334           {
0335         error_flag = 0;
0336         error_string = "";
0337           }
0338      
0339         return;
0340       }
0341 
0342     else if ( mg_vcmp ( &msg, "daq_end") == 0)
0343       {
0344         status = daq_end(out);
0345         if (status)
0346           {
0347         send_error(nc,out.str() );
0348           }
0349         return;
0350       }
0351 
0352     else if ( mg_vcmp ( &msg, "daq_open") == 0)
0353       {
0354         //    cout << __FILE__ << " " << __LINE__ << " daq_open request" << endl;
0355         daq_open();
0356         return;
0357       }
0358      
0359     else if ( mg_vcmp ( &msg, "daq_close") == 0)
0360       {
0361         //    cout << __FILE__ << " " << __LINE__ << " daq_open request" << endl;
0362         daq_close();
0363         return;
0364       }
0365 
0366     else if ( mg_vcmp ( &msg, "initial_update") == 0)
0367       {
0368         //cout << __FILE__ << " " << __LINE__ << "sending initial update" << endl;
0369         initial_ws_update(nc);
0370         return;
0371       }
0372 
0373     break;
0374       }
0375 
0376     case MG_EV_HTTP_REQUEST:
0377       {
0378     //cout << __FILE__ << " " << __LINE__ << " connection: " << nc << " uri: " << hm->uri.p << endl;
0379      
0380     if ( mg_vcmp ( &hm->uri, "/send_updates") == 0)
0381       {
0382         send_updates(nc);
0383         return;
0384       }
0385      
0386     else if ( mg_vcmp ( &hm->uri, "/daq_begin") == 0)
0387       {
0388         status = daq_begin(0,out);
0389         if (status)
0390           {
0391         send_status(nc,out.str() );
0392           }
0393         else
0394           {
0395         send_nothing(nc);
0396           }
0397         return;
0398       }
0399 
0400     else if ( mg_vcmp ( &hm->uri, "/daq_end") == 0)
0401       {
0402         status = daq_end(out);
0403         if (status)
0404           {
0405         send_status(nc,out.str() );
0406           }
0407         else
0408           {
0409         send_nothing(nc);
0410          
0411           }
0412         return;
0413       }
0414 
0415     else if ( mg_vcmp ( &hm->uri, "/daq_open") == 0)
0416       {
0417         //    cout << __FILE__ << " " << __LINE__ << " daq_open request" << endl;
0418         daq_open();
0419         send_nothing(nc);
0420         return;
0421       }
0422      
0423     else if ( mg_vcmp ( &hm->uri, "/daq_close") == 0)
0424       {
0425         //    cout << __FILE__ << " " << __LINE__ << " daq_open request" << endl;
0426         daq_close();
0427         send_nothing(nc);
0428         return;
0429       }
0430      
0431     mg_serve_http(nc, hm, s_http_server_opts);
0432     break;
0433       }
0434     case MG_EV_CLOSE:
0435       {
0436     //   nc->flags |=  MG_F_USER_1;
0437     //has_request=0;
0438     break;
0439       }
0440     default:
0441       break;
0442     }
0443 
0444 
0445 }
0446 
0447 
0448 
0449 
0450 int trigger_updates(struct mg_connection *nc)
0451 {
0452   if  (  error_flag)
0453     {
0454       update(nc, "Status", get_statusstring().c_str());
0455       error_flag = 0;
0456     }
0457   
0458   if  ( last_runstate   != daq_running() )
0459     {
0460       last_runstate  = daq_running();
0461       update(nc, "LINE", __LINE__);
0462       update(nc, "RunFlag", daq_running());
0463       update(nc, "Status", get_statusstring().c_str());
0464       update(nc, "RunNr", get_runnumber());
0465       update(nc, "Logging", get_loggingstring().c_str());
0466     }
0467   
0468   if  ( last_openflag != get_openflag() )
0469     {
0470       last_openflag = get_openflag();
0471       update(nc, "Logging", get_loggingstring().c_str());
0472       update(nc, "OpenFlag", get_openflag());
0473     }
0474   if  ( last_serverflag != get_serverflag() )
0475     {
0476       last_serverflag = get_serverflag();
0477       update(nc, "Logging", get_loggingstring().c_str());
0478       update(nc, "ServerFlag", get_serverflag());
0479     }
0480 
0481   if  ( rcdaqname_request_flag )
0482     {
0483       rcdaqname_request_flag = 0;
0484       update(nc, "Name", daq_get_myname().c_str());
0485     }
0486   
0487   if  ( speed_request_flag )
0488     {
0489       speed_request_flag = 0;
0490       update(nc, "MBps", daq_get_mb_per_second());
0491       update(nc, "Evtps", daq_get_events_per_second());
0492     }
0493   
0494   return 0;
0495 }
0496 
0497 void * mg_server (void *arg)
0498 {
0499 
0500   end_web_thread = 0;
0501   struct mg_mgr mgr;
0502   struct mg_connection *nc;
0503   
0504   int port = (int) *(int *)arg;
0505   stringstream portstring;
0506   portstring << port << ends;
0507   
0508   pthread_mutex_init( &M_ws_send, 0);
0509 
0510   
0511   last_runstate    = daq_running();
0512   last_runnumber   = get_runnumber();
0513   last_eventnumber = get_eventnumber();
0514   last_runvolume   = get_runvolume();
0515   last_runduration = get_runduration();
0516   last_openflag    = get_openflag();
0517   last_serverflag  = get_serverflag();
0518   rcdaqname_request_flag  = 0;
0519   speed_request_flag  = 0;
0520   
0521   //  last_current_filename; 
0522 
0523 
0524   mg_mgr_init(&mgr, NULL);
0525   nc = mg_bind(&mgr, portstring.str().c_str(), ev_handler);
0526   if (nc == NULL) 
0527     {
0528       cerr <<   __FILE__ << " " << __LINE__ <<  " Error starting server on port " << port << endl;
0529       return 0;
0530     }
0531   //   cout  << __FILE__ << " " << __LINE__ <<  " web server started on port " << port << endl;
0532    
0533   mg_set_protocol_http_websocket(nc);
0534   s_http_server_opts.document_root = HTMLDIR;
0535   s_http_server_opts.index_files = "control.html";
0536   s_http_server_opts.enable_directory_listing = "no";
0537    
0538 
0539   time_t last_time = time(0);
0540   time_t last_time_for_speed = last_time;
0541    
0542   while(!end_web_thread) 
0543     {
0544       mg_mgr_poll(&mgr, 1000);
0545 
0546       if ( time(0) - last_time_for_speed > speed_update_interval)
0547     {
0548       if (daq_running() ) speed_request_flag  = 1;
0549       last_time_for_speed = time(0);
0550     }
0551       
0552       trigger_updates(nc);
0553       
0554       if ( time(0) - last_time > 1)
0555     {
0556       send_ws_updates(nc);
0557       last_time = time(0);
0558     }
0559     }
0560   //   cout  << __FILE__ << " " << __LINE__ <<  " web server is ending"  << endl;
0561        
0562   return 0;
0563 }