3

Using Poco, I'm trying to emulate an AXIS camera web-server, that sends jpeg frames on clients request.

Each web response should be encoded with Content-Type: multipart/x-mixed-replace and a predefined boundary.

How can I do it with Poco? Thanks.

Cesar Ortiz
  • 884
  • 1
  • 8
  • 25

2 Answers2

1

The response.setContentType() is rigth, but when you make the sendBuffer(), Poco doesn't put the predefined boundary strings at top of each boundary block.

It is important to specify setChunkedTransferEncoding() to false to avoid chunk transfers, that it is not what I am asking for.

What I need is this: http://www.w3.org/Protocols/rfc1341/7_2_Multipart.html

If this is my data Buffer: "This is the first boundary block. A boundary block may continue in the next block. This is the second boundary block."

This is what I need to implement:

HTTP/1.1 200 OK
Date: Tue, 01 Dec 2013 10:27:30 GMT
Content-Length: 117
Content-Type: Multipart/mixed; boundary="sample_boundary";

--sample_boundary
This is the first boundary block. A boundary block may

--sample_boundary
continue in the next block. This is the second boundary block.

Playing around with that, I see that I must to split manually my buffer in order to get the desired boundaries.

This is how I actually do it:

std::ostream& ostr = response.send();

char frameBuffer[102410];
char fragment[1024];

string boundary = "--BOUNDARY--";
response.setChunkedTransferEncoding(false);
response.setContentType("multipart/x-mixed-replace; boundary=" + boundary);


//Split my frameBuffer in some fragments with boundary
unsigned int nBytes = sizeof(frameBuffer);
unsigned int _MAX_FRAGMENT_SIZE_ = sizeof(fragment);
unsigned int index=0;

response.setContentLength(frameLength);

while (nBytes>0){

    unsigned int size = (nBytes>_MAX_FRAGMENT_SIZE_)?_MAX_FRAGMENT_SIZE_:nBytes;
    memcpy(fragment, frameBuffer + index, size);

    //Enviamos el fragmento sin mas con su boundary correspondiente.
    ostr << boundary << "\r\n";
    ostr.write(fragment, size);
    ostr << "\r\n";

    index += size;
    nBytes -= size;
}

I thought Poco had tools to solve that. Thanks

Cesar Ortiz
  • 884
  • 1
  • 8
  • 25
  • We have it for [MailMessage](https://github.com/pocoproject/poco/blob/develop/Net/src/MailMessage.cpp), see [MailMessageTest::testReadWriteMultiPart](https://github.com/pocoproject/poco/blob/develop/Net/testsuite/src/MailMessageTest.cpp#L429) for an example of use. Should not be too much work to tweak it for HTTP. – Alex Mar 13 '13 at 15:42
  • 1
    Also, have a look at the [Poco::Net::MultipartWriter](http://pocoproject.org/docs/Poco.Net.MultipartWriter.html) class. – Günter Obiltschnig Mar 18 '13 at 18:24
  • The MultipartWriter class looks nice. I will make a try with it. Thanks Günter (and Alex) for your support. – Cesar Ortiz Mar 19 '13 at 12:51
0

Something along these lines should do:

using Poco::Net::HTTPRequestHandler;
using Poco::Net::HTTPServerRequest;
using Poco::Net::HTTPServerResponse;
using Poco::Net::HTTPRequestHandlerFactory;
using Poco::Net::HTTPServerParams;
using Poco::Net::HTTPServer;
using Poco::Net::ServerSocket;
using Poco::Net::SocketAddress;

struct AXISRequestHandler: public HTTPRequestHandler
{
    void handleRequest(HTTPServerRequest& request, HTTPServerResponse& response)
    {
        // ... get data to send back
        response.setContentType("multipart/x-mixed-replace; boundary=--MY_BOUND");
        response.sendBuffer(data, size);
    }
};

struct AXISRequestHandlerFactory: public HTTPRequestHandlerFactory
{
    HTTPRequestHandler* createRequestHandler(const HTTPServerRequest& request)
    {
        return new AXISRequestHandler;
    }
};

ServerSocket svs(SocketAddress("192.168.0.1", 8080));
HTTPServerParams* pParams = new HTTPServerParams;
// ... set server params here to your liking
HTTPServer srv(new AXISRequestHandlerFactory, svs, pParams);
srv.start(); // NB: server will fly off here (to its own thread)
Alex
  • 5,159
  • 4
  • 25
  • 33