--- a
+++ b/src/mediaserver/cdplugins/curlfetch.h
@@ -0,0 +1,66 @@
+#ifndef _CURLFETCH_H_INCLUDED_
+#define _CURLFETCH_H_INCLUDED_
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include <string>
+#include <functional>
+#include <memory>
+
+#include "bufxchange.h"
+#include "abuffer.h"
+
+//
+// Wrapper for a libcurl transfer. This uses the curl_easy interface
+// in a separate thread, so any number of transfers may be performed
+// in parallel.
+//
+// The transfer is aborted when the object is deleted, with proper
+// cleanup (in practise, if the curl thread is currently working
+// inside curl_easy_transfer, the curl fd is closed to abort any
+// current waiting).
+//
+// The end of transfer is signalled by pushing an empty buffer on the queue
+//
+// All methods are supposedly thread-safe
+class CurlFetch {
+public:
+    CurlFetch(const std::string& url);
+    ~CurlFetch();
+
+    void setTimeout(int secs);
+    
+    /// Start the transfer to the output queue.
+    bool start(BufXChange<ABuffer*> *queue, uint64_t offset = 0);
+
+    // Wait for HTTP headers. This allows, e.g. doing stuff depending
+    // on content-type before proceeding with the actual data transfer
+    bool waitForHeaders(int maxSecs = 0);
+    // Retrieve header value (after a successful waitForHeaders).
+    bool headerValue(const std::string& nm, std::string& val);
+
+    // Check if the curl thread is done and retrieve the results if it
+    // is. This does not wait, it returns false if the transfer is
+    // still running.
+    bool curlDone(int *curlcode, long *http_code);
+
+    // Callbacks
+
+    // A function to create the first buffer (typically for prepending
+    // a wav header to a raw pcm stream. If set this is called from
+    // the first curl write callback, before processing the curl data,
+    // so this happens at a point where the client may have had a look
+    // at the headers).
+    void setBuf1GenCB(std::function<bool(std::string& buf,void*,int)>);
+    // Called after curl_easy_perform returns
+    void setEOFetchCB(std::function<void(bool ok, u_int64_t count)> eofcb);
+    // Called every time we get new data from curl
+    void setFetchBytesCB(std::function<void(u_int64_t count)> fbcb);
+    
+    class Internal;
+private:
+    std::unique_ptr<Internal> m;
+};
+
+#endif /* _CURLFETCH_H_INCLUDED_ */