// . 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 ); }
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 ); }