//-----------------------------------------------------------------------------
/// SendHTTPErrorResponse
///
/// Sends an error page back
///
/// \param requestID An ID for a particular request; the plugin will get this
///  id as a parameter to the ProcessRequest( ) function
/// \param nErrorCode numeric identifier of the error to return
///
/// \return true if the response could be sent; false otherwise
//-----------------------------------------------------------------------------
bool SendHTTPErrorResponse(CommunicationID& requestID, int nErrorCode)
{
    // see if the response is streaming and rate limited
    if (ShouldResponseBeSent(requestID, true) == true)
    {
        // the message shouldn't be sent because of the rate limiting
        // return true though so the server thinks it was sent successfully
        return true;
    }

    Response* pResponse = NULL;

    if (MakeResponse(requestID, &pResponse) == false)
    {
        return false;
    }

    if (OutputHTTPError(pResponse->client_socket, nErrorCode) == false)
    {
        DestroyResponse(requestID, &pResponse);
        return false;
    }

    if (pResponse->m_bStreamingEnabled == false)
    {
        DestroyResponse(requestID, &pResponse);
    }

    return true;
}
//-----------------------------------------------------------------------------
/// SendRedirectResponse
///
/// Redirects the browser to a different URL than the one requested
///
/// \param requestID An ID for a particular request; the plugin will get this
///  id as a parameter to the ProcessRequest( ) function
/// \param pNewURL The url that the browser is being redirected to
///
/// \return true if the response could be sent; false otherwise
//-----------------------------------------------------------------------------
bool SendRedirectResponse(CommunicationID& requestID, const char* pNewURL)
{
    if (pNewURL == NULL)
    {
        return false;
    }

    // see if the response is streaming and rate limited
    if (ShouldResponseBeSent(requestID, true) == true)
    {
        // the message shouldn't be sent because of the rate limiting
        // return true though so the server thinks it was sent successfully
        return true;
    }

    Response* pResponse = NULL;

    if (MakeResponse(requestID, &pResponse) == false)
    {
        return false;
    }

    // generate the redirect html
    static char headerBuffer[COMM_BUFFER_SIZE];
    static char htmlBuffer[COMM_BUFFER_SIZE];

    sprintf_s(htmlBuffer, COMM_BUFFER_SIZE, "<html><body><a href=\"%s\">%s</a></body></html>", pNewURL, pNewURL);
    sprintf_s(headerBuffer, COMM_BUFFER_SIZE, "HTTP/1.0 301\r\nContent-Type: text/html\r\nContent-Length: %zd\r\nLocation: %s\r\n\r\n", strlen(htmlBuffer), pNewURL);

    bool nRes1;
    bool nRes2;
    nRes1 = pResponse->client_socket->Send(headerBuffer, (DWORD)strlen(headerBuffer));
    nRes2 = pResponse->client_socket->Send(htmlBuffer, (DWORD)strlen(htmlBuffer));

    pResponse->client_socket->close();

    if ((nRes1 == false) ||
        (nRes2 == false))
    {
        DestroyResponse(requestID, &pResponse);
        return false;
    }

    if (pResponse->m_bStreamingEnabled == false)
    {
        DestroyResponse(requestID, &pResponse);
    }

    return true;
}
//-----------------------------------------------------------------------------
/// SendMimeResponse
///
/// Sends a single buffer of raw data as the response which should be
/// interpreted by the recipient as being of the indicated MIME type
///
/// \param requestID An ID for a particular request; the plugin will get this
///  id as a parameter to the ProcessRequest( ) function
/// \param cpMimeType A string identifying which MIME type to use for
///  interpreting the data
/// \param cpData pointer to the data that should be sent as a response
/// \param uSizeInBytes number of bytes of data pointed to by cpData
///
/// \return true if the response could be sent; false otherwise
//-----------------------------------------------------------------------------
bool SendMimeResponse(CommunicationID& requestID, const char* cpMimeType, const char* cpData, unsigned int uSizeInBytes)
{
    if (cpMimeType == NULL)
    {
        Log(logERROR, "Failed to send %s response because data is NULL\n", cpMimeType);
        return false;
    }

    // see if the response is streaming and rate limited
    if (ShouldResponseBeSent(requestID, true) == true)
    {
        // the message shouldn't be sent because of the rate limiting
        // return true though so the server thinks it was sent successfully
        return true;
    }

    Response* pResponse = NULL;

    if (MakeResponse(requestID, &pResponse) == false)
    {
        return false;
    }

    // if Data is NULL then close streaming connection
    if (pResponse->m_bStreamingEnabled == true)
    {
        if (cpData == NULL)
        {
            const char* pstr = "--BoundaryString\r\n";
            pResponse->client_socket->Send(pstr, (unsigned int)strlen(pstr));
            CloseConnection(*pResponse);
            DestroyResponse(requestID, &pResponse);
            return true;
        }
    }

    if (Send(*pResponse, cpMimeType, cpData, uSizeInBytes) == false)
    {
        DestroyResponse(requestID, &pResponse);
        return false;
    }

    if (pResponse->m_bStreamingEnabled == false)
    {
        DestroyResponse(requestID, &pResponse);
    }

    return true;
}
//-----------------------------------------------------------------------------
/// SendFormattedTextResponse
///
/// Send a formatted string to be interpreted as text by the recipient.
///
/// \param requestID An ID for a particular request; the plugin will get this
///  id as a parameter to the ProcessRequest( ) function
/// \param cpFormat pointer to a character format that should be send as a
///  response; it is expected that this format consumes the remaining
///  parameters to this function
///
/// \return true if the response could be sent; false otherwise
//-----------------------------------------------------------------------------
bool SendFormattedTextResponse(CommunicationID& requestID, const char* cpFormat, ...)
{
    if (cpFormat == NULL)
    {
        Log(logERROR, "Failed to send formatted response because data is NULL\n");
        return false;
    }

    // see if the response is streaming and rate limited
    if (ShouldResponseBeSent(requestID, true) == true)
    {
        // the message shouldn't be sent because of the rate limiting
        // return true though so the server thinks it was sent successfully
        return true;
    }

    Response* pResponse = NULL;

    if (MakeResponse(requestID, &pResponse) == false)
    {
        Log(logERROR, "Failed to make a response for requestID %d\n", requestID);
        return false;
    }

    static char string[ 10240 ];
    va_list arg_ptr;

    va_start(arg_ptr, cpFormat);
    vsprintf_s(string, 10240, cpFormat, arg_ptr);
    va_end(arg_ptr);

    if (Send(*pResponse, "text/plain", string, (unsigned long)strlen(string)) == false)
    {
        Log(logERROR, "Failed to 'Send' response for requestID %d\n", requestID);
        DestroyResponse(requestID, &pResponse);
        return false;
    }

    if (pResponse->m_bStreamingEnabled == false)
    {
        DestroyResponse(requestID, &pResponse);
    }

    return true;
}
//-----------------------------------------------------------------------------
/// SendTextResponse
///
/// Sends a character string to be interpreted as text by the recipient.
///
/// \param requestID An ID for a particular request; the plugin will get this
///  id as a parameter to the ProcessRequest( ) function
/// \param cpData pointer to the text that should be sent as a response
///
/// \return true if the response could be sent; false otherwise
//-----------------------------------------------------------------------------
bool SendTextResponse(CommunicationID& requestID, const char* cpData)
{
    if (cpData == NULL)
    {
        Log(logERROR, "Failed to send text response because data is NULL\n");
        return false;
    }

    // see if the response is streaming and rate limited
    if (ShouldResponseBeSent(requestID, true) == true)
    {
        // the message shouldn't be sent because of the rate limiting
        // return true though so the server thinks it was sent successfully
        return true;
    }

    Response* pResponse = NULL;

    if (MakeResponse(requestID, &pResponse) == false)
    {
        Log(logERROR, "Failed to make a response for requestID %d to send content: %s\n", requestID, cpData);
        return false;
    }

    if (Send(*pResponse, "text/plain", cpData, (unsigned long)strlen(cpData)) == false)
    {
        Log(logERROR, "Failed to 'Send' response for requestID %d with content: %s\n", requestID, cpData);
        DestroyResponse(requestID, &pResponse);
        return false;
    }

    if (pResponse->m_bStreamingEnabled == false)
    {
        DestroyResponse(requestID, &pResponse);
    }

    return true;
}
//-----------------------------------------------------------------------------
/// SendBinaryResponse
///
/// Sends a single buffer of raw data as the response.
///
/// \param requestID An ID for a particular request; the plugin will get this
///  id as a parameter to the ProcessRequest( ) function
/// \param cpData pointer to the data that should be sent as a response
/// \param uSizeInBytes number of bytes of data pointed to by cpData
///
/// \return true if the response could be sent; false otherwise
//-----------------------------------------------------------------------------
bool SendBinaryResponse(CommunicationID& requestID,
                        const char* cpData,
                        unsigned int uSizeInBytes)
{
    if (cpData == NULL)
    {
        Log(logERROR, "Failed to send binary response because data is NULL\n");
        return false;
    }

    // see if the response is streaming and rate limited
    if (ShouldResponseBeSent(requestID, true) == true)
    {
        // the message shouldn't be sent because of the rate limiting
        // return true though so the server thinks it was sent successfully
        return true;
    }

    Response* pResponse = NULL;

    if (MakeResponse(requestID, &pResponse) == false)
    {
        Log(logERROR, "Failed to make a response for requestID %d\n", requestID);
        return false;
    }

    if (Send(*pResponse, "application/octet-stream", cpData, uSizeInBytes) == false)
    {
        Log(logERROR, "Failed to 'Send' response for requestID %d\n", requestID);

        if (pResponse->m_bStreamingEnabled == false)
        {
            DestroyResponse(requestID, &pResponse);
        }

        return false;
    }

    return true;
}
//-----------------------------------------------------------------------------
/// SendFileResponse
///
/// Sends the binary contents of a file to be interpreted by the recipient as
/// the type of file indicated by the file's extension.
///
/// \param requestID An ID for a particular request; the plugin will get this
///  id as a parameter to the ProcessRequest( ) function
/// \param cpData pointer to the filename that should be sent as a response
///
/// \return true if the response could be sent; false otherwise
//-----------------------------------------------------------------------------
bool SendFileResponse(CommunicationID& requestID, const char* cpFile)
{
    if (cpFile == NULL)
    {
        Log(logERROR, "Failed to send file response because filename is NULL\n");
        return false;
    }

    // see if the response is streaming and rate limited
    if (ShouldResponseBeSent(requestID, true) == true)
    {
        // the message shouldn't be sent because of the rate limiting
        // return true though so the server thinks it was sent successfully
        return true;
    }

    Response* pResponse = NULL;

    if (MakeResponse(requestID, &pResponse) == false)
    {
        Log(logERROR, "Failed to make a response for requestID %d to send file: %s\n", requestID, cpFile);
        return false;
    }

    // collect file data and generate response
    FILE* in;
    long fileSize;
    char* fileBuffer;
    fopen_s(&in, cpFile, "rb");    // read binary

    if (!in)
    {
        // file error, not found?
        OutputHTTPError(pResponse->client_socket, 404);     // 404 - not found
        return false;
    }

    // determine file size
    fseek(in, 0, SEEK_END);
    fileSize = ftell(in);
    fseek(in, 0, SEEK_SET);

    // allocate Buffer_ and read in file contents
    fileBuffer = new char[fileSize];
    fread(fileBuffer, sizeof(char), fileSize, in);
    fclose(in);

    bool bRes = Send(*pResponse, mimetypes[ FindMimeType(cpFile)].mime, fileBuffer, fileSize);

    if (bRes == false)
    {
        Log(logERROR, "Failed to 'Send' response for requestID %d\n", requestID);
        DestroyResponse(requestID, &pResponse);
    }

    delete [] fileBuffer;

    if (pResponse->m_bStreamingEnabled == false)
    {
        DestroyResponse(requestID, &pResponse);
    }

    return bRes;

}
示例#8
0
int main(void) 
{
  char inputBuffer[1024];
  
  InitializeRandomness();
  InitializeSimulation();


  while (1) 
  {

    int bytesReceived = ReceiveUntil(inputBuffer, sizeof(inputBuffer), '\n');
    if (bytesReceived < 0) 
    {
      break;
    }
    if (bytesReceived == 0) 
    {
      continue;
    }
    query *pCurrentQuery = ParseQuery(inputBuffer);
    response *pCurrentResponse = GenerateBlankResponse();
    switch (pCurrentQuery->type)
    {
      case QUERY_ALL:
      {
        printf("Query All\n");
        // List all servers in network
        link *listItem = serverList->root;
        while (listItem != NULL) 
        {
          serverInfo *server = listItem->object;
          if (server == NULL) 
          {
            continue;
          }
          AddToResponse(pCurrentResponse, "server:");
          AddToResponse(pCurrentResponse, server->name);
          AddToResponse(pCurrentResponse, ":");
          listItem = listItem->next;
        } 
        break;
      }
      case QUERY_SERVER:
      {
        printf("Query Server\n");
        // List all instances on a server
        char *name = (char *)pCurrentQuery->data;
        serverInfo *server = FindServer(name);
        if (server == NULL) 
        {
          continue;
        }
        link *listItem = server->instances->root;
        while (listItem != NULL) 
        {
          instanceInfo *instance = listItem->object;
          if (instance == NULL) 
          {
            continue;
          }
          AddToResponse(pCurrentResponse, "instance:");
          AddToResponse(pCurrentResponse, instance->name);
          AddToResponse(pCurrentResponse, ":");
          listItem = listItem->next;
        }
        break;
      }
      case QUERY_ONE:
      {
        QueryOne(pCurrentQuery, pCurrentResponse);
        break;
      }
      case QUERY_ADMIN:
      {
        // Send admin info for one instance
        printf("Query Admin\n");
        int version = pCurrentQuery->data[0];
        if (version != 1)
        {
          printf("Invalid Query\n");
          _terminate(0);
        }
        char instanceName[64];
        strncpy(instanceName, (char *)&pCurrentQuery->data[1], 64);
        instanceInfo *instance = FindInstance(instanceName);
        if (instance == NULL) 
        {
          printf("Instance Not Found\n");
          _terminate(0);
        }
        AddToResponse(pCurrentResponse, "admin:");
        char number[12];
        cgc_memset(number, 0, sizeof(number));
        uint16_t adminPort = *(uint16_t *)((uint8_t *)FLAG_PAGE + instance->adminPortOffset);
        sprintf(number, "$x", (int)adminPort);
        AddToResponse(pCurrentResponse, number);
        AddToResponse(pCurrentResponse, ":");
        break;
      }
      default:
      {
        // Invalid Query
        printf("Invalid Query\n");
        _terminate(0);
        break;
      }
    }
    SendResponse(pCurrentResponse);
    pCurrentQuery = DestroyQuery(pCurrentQuery);
    pCurrentResponse = DestroyResponse(pCurrentResponse);
  }
  return 0;
}