// . returns false if blocked, true otherwise
// . sets g_errno on error
// . we are called by Parms::sendPageGeneric() to handle this request
//   which was called by Pages.cpp's sendDynamicReply() when it calls 
//   pg->function() which is called by HttpServer::sendReply(s,r) when it 
//   gets an http request
// . so "hr" is on the stack in HttpServer::requestHandler() which calls
//   HttpServer::sendReply() so we gotta copy it here
bool sendPageInject ( TcpSocket *sock , HttpRequest *hr ) {

	if ( ! g_conf.m_injectionsEnabled ) {
		g_errno = EINJECTIONSDISABLED;//BADENGINEER;
		log("inject: injection disabled");
		return g_httpServer.sendErrorReply(sock,500,"injection is "
						   "disabled by "
						   "the administrator in "
						   "the master "
						   "controls");
	}

	char format = hr->getReplyFormat();
	char *coll  = hr->getString("c",NULL);

	// no url parm?
	if ( format != FORMAT_HTML && ! coll ) {//hr->getString("c",NULL) ) {
		g_errno = ENOCOLLREC;
		char *msg = mstrerror(g_errno);
		return g_httpServer.sendErrorReply(sock,g_errno,msg,NULL);
	}

	if ( g_repairMode ) { 
		g_errno = EREPAIRING;
		char *msg = mstrerror(g_errno);
		return g_httpServer.sendErrorReply(sock,g_errno,msg,NULL);
	}

	// get collection rec
	CollectionRec *cr = g_collectiondb.getRec ( coll );
	if ( ! cr ) {
		g_errno = ENOCOLLREC;
		char *msg = mstrerror(g_errno);
		return g_httpServer.sendErrorReply(sock,g_errno,msg,NULL);
	}

	// no permmission?
	bool isMasterAdmin = g_conf.isMasterAdmin ( sock , hr );
	bool isCollAdmin = g_conf.isCollAdmin ( sock , hr );
	if ( ! isMasterAdmin && ! isCollAdmin ) {
		g_errno = ENOPERM;
		char *msg = mstrerror(g_errno);
		return g_httpServer.sendErrorReply(sock,g_errno,msg,NULL);
	}

	// make a new state
	Msg7 *msg7;
	try { msg7= new (Msg7); }
	catch ( ... ) { 
		g_errno = ENOMEM;
		log("PageInject: new(%i): %s", 
		    (int)sizeof(Msg7),mstrerror(g_errno));
	       return g_httpServer.sendErrorReply(sock,500,mstrerror(g_errno));
	}
	mnew ( msg7, sizeof(Msg7) , "PageInject" );

	// save some state info into msg7 directly
	msg7->m_socket = sock;
	msg7->m_format = format;
	msg7->m_replyIndexCode = 0;
	msg7->m_replyDocId = 0;
	
	msg7->m_hr.copy ( hr );

	// use Parms.cpp like how we set GigablastRequest to initialize parms
	// from the http request. i.e. setGigablastRequest(). 
	// the InjectionRequest::ptr_*  members will reference into
	// msg7->m_hr buffers so they should be ok.
	InjectionRequest *ir = &msg7->m_injectionRequest;
	setInjectionRequestFromParms (sock, &msg7->m_hr, cr, ir );

	// a scrape request?
	if ( ir->ptr_queryToScrape ) {
		//char *uf="http://www.google.com/search?num=50&"
		//	"q=%s&scoring=d&filter=0";
		msg7->m_linkDedupTable.set(4,0,512,NULL,0,false,0,"ldtab");
		if ( ! msg7->scrapeQuery ( ) ) return false;
		return sendHttpReply ( msg7 );
	}

	// if no url do not inject
	if ( ! ir->ptr_url )
		return sendHttpReply ( msg7 );

	// this will be NULL if the "content" was empty or not given
	//char *content = ir->ptr_content;

	// . try the uploaded file if nothing in the text area
	// . this will be NULL if the "content" was empty or not given
	//if ( ! content ) content = ir->ptr_contentFile;

	// forward it to another shard?
	//Host *host = getHostToHandleInjection ( ir->ptr_url );
	// if we are the responsible host, continue onwards with the injection
	// if ( host == g_hostdb.m_myHost ) {
	// 	// just do it now
	// 	if ( ! injectForReals ( ir , this , doneLocalInjectWrapper ) ) 
	// 		// if it would block, return false
	// 		return false;
	// 	// all done already...
	// 	log("inject: did not block");
	// 	mdelete ( msg7, sizeof(Msg7) , "PageInject" );
	// 	delete (msg7);
	// 	g_errno = EBADENGINEER;
	// 	char *msg = mstrerror(g_errno);
	// 	return g_httpServer.sendErrorReply(sock,g_errno,msg,NULL);
	// }

	// when we receive the udp reply then send back the http reply
	// we return true on success, which means it blocked... so return false
	if ( msg7->sendInjectionRequestToHost(ir,msg7,sendHttpReplyWrapper)) 
		return false;

	if ( ! g_errno ) {
		log("inject: blocked with no error!");
		char *xx=NULL;*xx=0; 
	}
		
	// error?
	log("inject: error forwarding reply: %s (%i)",  mstrerror(g_errno),
	    (int)g_errno);
	// it did not block, i gues we are done
	return sendHttpReply ( msg7 );
}
Beispiel #2
0
int main(int argc, char* argv[]) {
  Config config;
  int socket;
  int returnStatus = 0;
  struct sockaddr_in tcpServer;

  /* server is running */
  server_running = 1;
  server_pid = getpid();

  /* no requests yet! */
  total_requests = 0;

  /* make sure we've got a config file */
  if(argc < 2) {
    fprintf(stderr, "Usage: %s <config_file>\n", argv[0]);
    exit(1);
  }

  /* load the config file, abort on error */
  if(load_config(&config, argv[1]) < 0) {
    fprintf(stderr, "Error parsing config file %s\n", argv[1]);
    exit(1);
  }

  /* create a UDP socket or die */
  if((socket = e_socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) {
    exit(1);
  }

  /* allow re-use of socket addresses to avoid 'already bound' problems */
  int v = 1;
  returnStatus = setsockopt(socket, SOL_SOCKET, SO_REUSEADDR, &v, sizeof(v));
  if(returnStatus < 0) {
    perror("Setting socket option failed");
    exit(1);
  }
  
  /* set up the TCP server */
  tcpServer.sin_family = AF_INET;
  tcpServer.sin_port = htons(config.port);
  tcpServer.sin_addr.s_addr = INADDR_ANY;

  /* bind socket to the server */
  returnStatus = bind(socket, (struct sockaddr*)&tcpServer, sizeof(tcpServer));
  if(returnStatus < 0) {
    perror("Bind Failed");
    if(close(socket) < 0) {
      perror("Error closing socket");
    }
    exit(1);
  }
  
  /* allow a given signal to terminate server */
  struct sigaction act;
  memset(&act, 0, sizeof(act));
  act.sa_handler = sigshutdown_handler;
  sigaction(config.shutdown_signal, &act, 0);

  /* open log file if enabled */
  if(config.logging) {
    logfile = fopen_or_die(config.logfile, "w");
  }
  
  /* run indefinitely */
  int connect_fd;
  if(config.logging) {
    slog(logfile, "Server started\n");
    slog(logfile, "Listening on port %d\n", config.port); 
  }

  /* listen for connections */
  returnStatus = listen(socket, BACK_LOG);
  if(returnStatus < 0) {
    perror("Error listening for connection");
  }

  while(server_running) {
    /* accept an incoming connection from queue */
    if((connect_fd = accept(socket, NULL, NULL)) < 0) {
      /* may have been interrupted, safe to try again */
      if(errno == EINTR || errno == EAGAIN) {
        continue;
      } else {
        perror("Unable to accept connection");
        exit(EXIT_FAILURE);
      }
    } else {
      /* read in an entire HTTP request */
      FILE* record_file = NULL;
      if(config.recording) {
        record_file = fopen_or_die(config.recordfile, "w");
      }
      char* request = readRequest(connect_fd, record_file);
      /* ensure is a valid request i.e is a GET and hostname matches */
      char* file_path = malloc_or_die(BUFFER_LEN);
      if(parseRequest(connect_fd, request, file_path, &config)) {
        ReplyParams r;
        r.connect_fd = connect_fd;
        strncpy(r.file_path, file_path, BUFFER_LEN);
        r.c = &config;
        r.logfile = logfile;
        sendHttpReply(&r);
      }

      /* successfully handled a request, count it */
      total_requests++;

      /* shutdown & close client connection */
      close(connect_fd);
    }
  }

  if(close(socket) < 0) {
    perror("Error closing socket");
  }
  /* cleanup & exit */
  if(config.logging) {
    slog(logfile, "Terminating server\n");
    fclose(logfile);
  }
  return 0;
}
void sendHttpReplyWrapper ( void *state ) {
	sendHttpReply ( state );
}