Esempio n. 1
0
 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);
}