/* * This file is part of rasdaman community. * * Rasdaman community is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Rasdaman community is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with rasdaman community. If not, see . * * Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / rasdaman GmbH. * * For more information please see * or contact Peter Baumann via . / /** * SOURCE: rasmgr_comm.cc * * MODULE: rasmgr * CLASS: HTTPComm * * PURPOSE: * Performs reliable, but blocking HTTP communication. used by the slave rasmgr * * COMMENTS: * Will be removed, the plan is to have only non-blocking communication * */ #include "rasmgr_comm.hh" #ifdef X86 #define r_Socklen_t socklen_t #endif #ifdef AIX #define r_Socklen_t socklen_t #endif #ifdef SOLARIS #define r_Socklen_t socklen_t #endif #ifdef DECALPHA #define r_Socklen_t int #endif #include "debug.hh" HTTPComm::HTTPComm() { //parentPID=getpid(); listen_socket=-1; exitRequest=false;; } HTTPComm::~HTTPComm() { ENTER("HTTPComm::~HTTPComm: enter." ); closeListenSocket(); LEAVE("HTTPComm::~HTTPComm: leave." ); } void HTTPComm::closeListenSocket() { ENTER("HTTPComm::closeListenSocket: enter." ); if(listen_socket>=0) close(listen_socket); LEAVE("HTTPComm::closeListenSocket: leave." ); } int HTTPComm::sendAnswer(int socket,int len) { int result = 0; ENTER("HTTPComm::sendAnswer: enter." << std::endl ); int write_count=writeWholeMessage(socket,outBuffer,len); // adapted logic to single point of return -- PB 26-may-2003 if(write_count<0) { TALK( "HTTPComm::sendAnswer: Error writing answer" ); result = -1; } else result = 0; LEAVE("HTTPComm::sendAnswer: leave. result=" << result ); return result; } int HTTPComm::getMessage() { ENTER("HTTPComm::getMessage: enter." << std::endl ); int socket=realGetMessage(); if(socket>0) { header=inBuffer; body=strstr(inBuffer,"\r\n\r\n"); if(body!=NULL) { *body=0; body+=4; } else { close(socket); socket = -1; } } LEAVE("HTTPComm::getMessage: leave. socket=" << socket ); return socket; } int HTTPComm::realGetMessage() { struct sockaddr_in clientname; r_Socklen_t size=sizeof(clientname); ENTER("HTTPComm::getRealMessage: enter." ); int socket=accept(listen_socket,(struct sockaddr*)&clientname,&size); if(socket<0) { TALK( "HTTPComm::realGetMessage: Error accepting connection."); socket = -1; // normalize error feedback } if (socket >= 0) // accept() worked fine, so wa can continue { int read_count=readWholeMessage(socket,inBuffer,MAXMSG); if(read_count<0) { TALK( "HTTPComm::realGetMessage: Error reading message."<p_proto); if(sock<0) { TALK("HTTPComm::makeSocket: socket failed. errno=" << errno ); exitbyerror("make socket"); } name.sin_family=AF_INET; name.sin_port=htons(port); name.sin_addr.s_addr=htonl(INADDR_ANY); #ifdef SO_REUSEADDR int val = 1; int len = sizeof( val ); if(setsockopt( sock, SOL_SOCKET, SO_REUSEADDR, (char*)&val, len )) { TALK( "HTTPComm::makeSocket: Can't set address reusable: "<< strerror(errno) ); } #endif int sockResult = bind(sock,(sockaddr*)&name,sizeof(name)); TALK( "HTTPComm::makeSocket: bind() with socket=" << sock << ", name.sin_port="<< name.sin_port << " returned " << sockResult ); if(sockResult < 0) { TALK( "HTTPComm::makeSocket: bind failed: "<< strerror(errno) ); exitbyerror("bind"); // This is OK to exit, program just starts and we can't have an address } ENTER("HTTPComm::makeSocket: leave. socket=" << sock << std::endl ); return sock; } void HTTPComm::shouldExit() { exitRequest=true; } bool HTTPComm::isMessage(const char *messageStart) { ENTER("HTTPComm::isMessage: enter. messageStarte=" << messageStart ); bool rasp= (strncasecmp(header,messageStart,strlen(messageStart))==0) ? true:false; if(rasp) { TALK("HTTPComm::isMessage: (b) Message=" << messageStart ); } LEAVE("HTTPComm::isMessage: leave. result=" << rasp ); return rasp; } // int readWholeMessage(int socket,char *destBuffer,int buffSize) { ENTER("HTTPComm::readWholeMessage: enter. socket=" << socket << ", destBuffer=" << destBuffer << ", buffSize=" << buffSize ); // we read what is comming in until we encounter a '\0' // this is our end-sign. int totalLength=0; int redNow; while(1) { redNow = read(socket,destBuffer+totalLength,buffSize-totalLength); if(redNow == -1) { if(errno == EINTR) continue; // read was interrupted by signal TALK("HTTPComm::readWholeMessage: read error. errno=" << errno ); return -1; // another error } totalLength+=redNow; if(destBuffer[totalLength-1]==0) break; // THE END } LEAVE("HTTPComm::readWholeMessage: leave. totalLength=" << totalLength ); return totalLength; } int writeWholeMessage(int socket,char *destBuffer,int buffSize) { ENTER("HTTPComm::writeWholeMessage: enter. socket=" << socket << ", destBuffer=" << destBuffer << ", buffSize=" << buffSize ); // we write the whole message, including the ending '\0', which is already in // the buffSize provided by the caller int totalLength=0; int writeNow; while(1) { writeNow = write(socket,destBuffer+totalLength,buffSize-totalLength); if(writeNow == -1) { if(errno == EINTR) continue; // read was interrupted by signal TALK("HTTPComm::writeWholeMessage: read error. errno=" << errno ); return -1; // another error } totalLength+=writeNow; if( totalLength==buffSize ) break; // THE END } LEAVE("HTTPComm::writeWholeMessage: leave. totalLength=" << totalLength ); return totalLength; }