std::string Channel::eventsToString() const { return eventsToString( fd_, events_ ); }
/** * Advance for online Indirect execution */ void Redirector::advanceIndirect(){ const int MAX=JAIL_NET_BUFFER_SIZE; //Buffer size to read const int POLLBAD=POLLERR|POLLHUP|POLLNVAL; const int POLLREAD=POLLIN|POLLPRI; const int polltimeout= 100; // 0.1 sec States oldstate=state; switch(state){ case begin:{ sock=socket(AF_INET,SOCK_STREAM,0);//0= IP protocol if(sock<0){ state=error; //No socket available break; } int on=1; setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); //fdblock(sock,false); state=connecting; } /* no break */ case connecting:{ struct sockaddr_in sdir; memset(&sdir, 0, sizeof(sdir)); sdir.sin_family = AF_INET; inet_pton(AF_INET,"127.0.0.1",&sdir.sin_addr); sdir.sin_port = htons( port ); if(connect(sock, (const sockaddr*)&sdir, sizeof(sdir))==0){ //fdblock(sock,true); state=connected; break; }else{ syslog(LOG_INFO, "socket connect to (127.0.0.1:%d) error: %m",(int)port); } if(timeout<time(NULL)){ syslog(LOG_ERR, "socket connect timeout: %m"); state=error; } break; } case connected:{ //Poll to write and read from program and net if(ws->isClosed()){ syslog(LOG_INFO,"Websocket closed by client"); state = end; break; } if(ws->isReadBuffered()) netbuf += ws->receive(); //Read client data struct pollfd devices[2]; devices[0].fd=sock; devices[1].fd=ws->getSocket(); char buf[MAX]; if(netbuf.size()) devices[0].events=POLLREAD|POLLOUT; else devices[0].events=POLLREAD; devices[1].events=POLLREAD; int res=poll(devices,2,polltimeout); if(res==-1) { //Error syslog(LOG_INFO,"pool error %m"); state = error; break; } if(res==0) break; //Nothing to do syslog(LOG_INFO,"poll: server socket %d %s", devices[0].revents,eventsToString(devices[0].revents).c_str()); syslog(LOG_INFO,"poll: client socket %d %s", devices[1].revents,eventsToString(devices[1].revents).c_str()); if(devices[1].revents & POLLREAD){ //Read vnc client data netbuf += ws->receive(); } if(devices[0].revents & POLLREAD){ //Read vncserver data int readsize=read(sock,buf,MAX); if(readsize <= 0){ //Socket closed or error if(readsize < 0) syslog(LOG_INFO,"Receive from vncserver error: %m"); else syslog(LOG_INFO,"Receive from vncserver size==0: %m"); state=ending; break; } ws->send(string(buf,readsize),BINARY_FRAME); } if(netbuf.size()>0 && (devices[0].revents & POLLOUT)){ //Write to vncserver int written=write(sock,netbuf.data(),netbuf.size()); if(written <=0) { //close or error if(written<0) syslog(LOG_INFO,"Send to vncserver error: %m"); state=ending; break; } netbuf.erase(0,written); } if((devices[0].revents & POLLBAD) && !(devices[0].revents & POLLREAD)){ syslog(LOG_INFO,"Vncserver end or I/O error: %m %d %s",devices[0].revents,eventsToString(devices[0].revents).c_str()); state=ending; break; } break; } case ending: state=end; /* no break */ case end: case error: if(ws->isClosed()) usleep(50000); else ws->close(); break; } if(oldstate != state) syslog(LOG_INFO,"New redirector state %d => %d",oldstate,state); }
/** * Advance for batch execution */ void Redirector::advanceBatch(){ int oldstate=state; const int MAX=JAIL_NET_BUFFER_SIZE; //Buffer size to read const int POLLBAD=POLLERR|POLLHUP|POLLNVAL; const int POLLREAD=POLLIN|POLLPRI; const int polltimeout= 100; // 0.1 sec switch(state){ case begin: if(fdps<0) { state=error; //fd pseudo terminal error break; } Util::fdblock(fdps,false); /* no break */ case connecting: state=connected; /* no break */ case connected:{ //Poll to read from program struct pollfd devices[1]; devices[0].fd=fdps; char buf[MAX]; devices[0].events=POLLREAD; //removed |POLLOUT int res=poll(devices,1,polltimeout); if(res==-1) { //Error state = error; break; } if(res==0) break; //Nothing to do //syslog(LOG_INFO,"poll: program %d %s.", // devices[0].revents,eventsToString(devices[0].revents).c_str()); if(devices[0].revents & POLLREAD){ //Read program output int readsize=read(fdps,buf,MAX); if(readsize == 0){ syslog(LOG_INFO,"program output end: %m"); state=end; break; } if(readsize < 0){ syslog(LOG_INFO,"program output read error: %m"); state=error; break; //program output read error } if(readsize >0) { netbuf += string(buf,readsize); break; } } if(devices[0].revents & POLLBAD){ syslog(LOG_INFO,"Program end or I/O error: %m %d %s.", devices[0].revents,eventsToString(devices[0].revents).c_str()); state=error; break; } break; } case ending: state=end; /* no break */ case end: case error: usleep(50000); break; } if(oldstate != state) syslog(LOG_INFO,"New redirector state %d => %d",oldstate,state); }
/** * Advance for online execution */ void Redirector::advanceOnline(){ const int MAX=JAIL_NET_BUFFER_SIZE; //Buffer size to read const int POLLBAD=POLLERR|POLLHUP|POLLNVAL; const int POLLREAD=POLLIN|POLLPRI; const int polltimeout= 100; // 0.1 sec States oldstate=state; switch(state){ case begin:{ if(fdps<0) { state=error; //fd pseudo terminal error break; } Util::fdblock(fdps,false); state=connected; case connected:{ //Poll to write and read from program and net if(ws->isReadBuffered()) programbuf += ws->receive(); struct pollfd devices[2]; devices[0].fd=fdps; devices[1].fd=ws->getSocket(); char buf[MAX]; if(programbuf.size()) devices[0].events=POLLREAD|POLLOUT; else devices[0].events=POLLREAD; devices[1].events=POLLREAD; int res=poll(devices,2,polltimeout); if(res==-1) { //Error syslog(LOG_INFO,"pool error %m"); state = error; break; } if(res==0) break; //Nothing to do syslog(LOG_INFO,"poll: program %d %s", devices[0].revents,eventsToString(devices[0].revents).c_str()); if(devices[1].revents & POLLREAD) programbuf += ws->receive(); if((devices[0].revents & POLLREAD) && !isOutputBufferFull()){ //Read program output int readsize=read(fdps,buf,MAX); if(readsize <= 0){ syslog(LOG_INFO,"program output read error: %m"); state=ending; break; //program output read error } if(readsize >0) { ws->send(string(buf,readsize)); } } if(programbuf.size()>0 && (devices[0].revents & POLLOUT)){ //Write to program int written=write(fdps,programbuf.data(),programbuf.size()); if(written <=0) { syslog(LOG_INFO,"Write to program error: %m"); state=ending; break; } programbuf.erase(0,written); } if((devices[0].revents & POLLBAD) && !(devices[0].revents & POLLREAD)){ syslog(LOG_INFO,"Program end or I/O error: %m %d %s",devices[0].revents,eventsToString(devices[0].revents).c_str()); state=ending; break; } break; } case ending:{ if(isSilent()){ syslog(LOG_INFO,"Program terminated with no output"); ws->send("\nProgram terminated with no output\n"); } if(messageBuf.size()>0){ syslog(LOG_INFO,"Add jail message to output"); ws->send(messageBuf); messageBuf=""; } } state=end; /* no break */ case end: case error: if(ws->isClosed()) usleep(50000); else ws->close(); break; } } if(oldstate != state) syslog(LOG_INFO,"New redirector state %d => %d",oldstate,state); }