從內存播放Flash

前提:
    被要求Flash必須加密,不能在硬盤上留下文件。

起點:
      Flash 播放器的屬性Movie接受本地文件名 或者 HTTP URL。

首先當然是在網絡上尋找解決方案了。找了半天,發現一個國內的,一個國外的。都在出售。
奇怪的是,他們不約而同的都是用了Delphi。
根據瞭解的人透露,它是利用了Flash一個未公開的屬性MovieData, 該屬性文檔中沒有記錄,但是從名稱可以看出應該是應該是接受數據片的。

其國內的那一版目前還不支持最新的flash播放器。這讓人不能不有點擔憂。 因此還是儘量照自己的思路來。


思路:
    最開始考慮的就是建一個協議(類似於rtsp的樣子)來代替http,並把請求轉到本地守護進程。
    後來又想到還不如直接建立一個簡陋的http服務器,直接使用http url , 這樣子肯定是可行的,於是就着手寫http服務器了。
    寫了個簡單的測試程序,監聽了一些http包,發現即使建立個簡陋的http服務器,也需要了解一下rfc2612的,考慮到flash不同版本可能識別的響應及其標籤,響應頭還是蠻複雜的。
    看rfc2612的時候突然想到, 建立http服務器是虛擬一個url;如果能夠虛擬一個本地文件名,是不是更簡單些呢? 照着這個思路,找了個把小時,當然也走了不少的彎路。最終發現可以用管道來處理。

    因爲管道客戶端也是用CreateFile, ReadFile來處理的, 與普通文件一樣。這樣子就可以用管道名稱來代替文件名來欺騙一下flash樂^_^

    被欺騙的Flash讀文件的時候:CreateFile, ReadFile實際上是讀的是管道,只是他自己不知道而已.  而我們可以向管道寫入任何內容,這不就達到目的了麼?

    寫了段代碼驗證了一下,確實可行。 而且還模擬了網絡的流環境(每次讀10字節,延遲3ms),發現效果不錯,正如預料的一樣。

    下面貼出來的代碼來資源是測試程序,比較零亂。如果你仔細看了上面的內容,並且對於提到的屬於沒什麼不解的話,應該就不用看下面的代碼了。 附上來僅僅是爲了備忘。

    代碼是一個console程序, vs2003環境。
    假設有個樣例Flash爲Blue.swf。
    設定的管道名稱爲: //./pipe/egbpipe 
    
    驗證時先運行本程序,並保證blue.swf存在。然後打開flash播放器,用她播放文件"//./pipe/egbpipe"。

    代碼開始:
    -------------
// PipeService.cpp : 定義控制檯應用程序的入口點。
//

#include "stdafx.h"

#define BUFSIZE 1024
#define PIPE_TIMEOUT 1000

int __main(void);
int MyErrExit(char*);
int _tmain(int argc, _TCHAR* argv[])
{
 __main();
 return 0;
}

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <windows.h>
 
VOID InstanceThread(LPVOID);
VOID GetAnswerToRequest(LPTSTR, LPTSTR, LPDWORD);
VOID GetAnswerToRequest(HANDLE hFile);
int xx = 0;
 

/*

//./pipe/egbpipe

*/

int __main(void)
{
   BOOL fConnected;
   DWORD dwThreadId;
   HANDLE hPipe, hThread;
   LPTSTR lpszPipename = "////.//pipe//egbpipe";
 
// The main loop creates an instance of the named pipe and
// then waits for a client to connect to it. When the client
// connects, a thread is created to handle communications
// with that client, and the loop is repeated.
 
   for (;;)
   {
      hPipe = CreateNamedPipe(
          lpszPipename,             // pipe name
          PIPE_ACCESS_DUPLEX,       // read/write access
          PIPE_TYPE_MESSAGE |       // message type pipe
          PIPE_READMODE_MESSAGE |   // message-read mode
          PIPE_WAIT,                // blocking mode
          PIPE_UNLIMITED_INSTANCES, // max. instances 
          BUFSIZE,                  // output buffer size
          BUFSIZE,                  // input buffer size
          PIPE_TIMEOUT,             // client time-out
          NULL);                    // no security attribute

      if (hPipe == INVALID_HANDLE_VALUE)
          MyErrExit("CreatePipe");
 
      // Wait for the client to connect; if it succeeds,
      // the function returns a nonzero value. If the function returns
      // zero, GetLastError returns ERROR_PIPE_CONNECTED.
 
      fConnected = ConnectNamedPipe(hPipe, NULL) ?
         TRUE : (GetLastError() == ERROR_PIPE_CONNECTED);
 
      if (fConnected)
      {
      // Create a thread for this client.
         hThread = CreateThread(
            NULL,              // no security attribute
            0,                 // default stack size
            (LPTHREAD_START_ROUTINE) InstanceThread,
            (LPVOID) hPipe,    // thread parameter
            0,                 // not suspended
            &dwThreadId);      // returns thread ID

         if (hThread == NULL)
            MyErrExit("CreateThread");
         else
            CloseHandle(hThread);
 
      }
      else
        // The client could not connect, so close the pipe.
         CloseHandle(hPipe);
   }
   return 1;
}
 
VOID InstanceThread(LPVOID lpvParam)
{
   CHAR chRequest[BUFSIZE];
   CHAR chReply[BUFSIZE];
   DWORD cbBytesRead, cbReplyBytes, cbWritten;
   BOOL fSuccess;
   HANDLE hPipe;
 
// The thread's parameter is a handle to a pipe instance.
 
   hPipe = (HANDLE) lpvParam;
 
  // while (1)
 &

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章