📄 hxbackend.cpp
字号:
/* ***** BEGIN LICENSE BLOCK ***** * Source last modified: $Id: hxbackend.cpp,v 1.32.2.8 2004/11/23 00:24:25 rggammon Exp $ * * * Portions Copyright (c) 1995-2002 RealNetworks, Inc. All Rights Reserved. * * The contents of this file, and the files included with this file, * are subject to the current version of the RealNetworks Public * Source License (the "RPSL") available at * http://www.helixcommunity.org/content/rpsl unless you have licensed * the file under the current version of the RealNetworks Community * Source License (the "RCSL") available at * http://www.helixcommunity.org/content/rcsl, in which case the RCSL * will apply. You may also obtain the license terms directly from * RealNetworks. You may not use this file except in compliance with * the RPSL or, if you have a valid RCSL with RealNetworks applicable * to this file, the RCSL. Please see the applicable RPSL or RCSL for * the rights, obligations and limitations governing use of the * contents of the file. * * Alternatively, the contents of this file may be used under the * terms of the GNU General Public License Version 2 or later (the * "GPL") in which case the provisions of the GPL are applicable * instead of those above. If you wish to allow use of your version of * this file only under the terms of the GPL, and not to allow others * to use your version of this file under the terms of either the RPSL * or RCSL, indicate your decision by deleting the provisions above * and replace them with the notice and other provisions required by * the GPL. If you do not delete the provisions above, a recipient may * use your version of this file under the terms of any one of the * RPSL, the RCSL or the GPL. * * This file is part of the Helix DNA Technology. RealNetworks is the * developer of the Original Code and owns the copyrights in the * portions it created. * * This file, and the files included with this file, is distributed * and made available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY * KIND, EITHER EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS * ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET * ENJOYMENT OR NON-INFRINGEMENT. * * Technology Compatibility Kit Test Suite(s) Location: * http://www.helixcommunity.org/content/tck * * Contributor(s): * * ***** END LICENSE BLOCK ***** *//* XXXRGG: Undefine DEBUG so we don't pull in nsDebug stuff */#ifdef DEBUG# undef DEBUG#endif#ifdef _UNIX#include <errno.h>#include <unistd.h>#include <fcntl.h>#include <sys/socket.h>#endif#include <sys/time.h>#include <sys/types.h>#include <sys/wait.h>#include <signal.h>#include "npplat.h"#include "hxbackend.h"#include "asprintf.h"#include "tokenizer.h"#include "nsIServiceManager.h"#include "nsIComponentManager.h"#include "nsIDOMWindow.h"#define EXIT_CODE_UNKNOWN 0#define EXIT_CODE_HXPLAY_NOT_FOUND 10const int CHXPlayerBackend::m_iBackendVersion = 1;const int CHXPlayerBackend::m_iPlayerVersion = 1;typedef enum{ FIND_PLAYER_STATE_INIT, FIND_PLAYER_STATE_OVERRIDE, FIND_PLAYER_STATE_REALPLAY, FIND_PLAYER_STATE_HXPLAY, FIND_PLAYER_STATE_FAILED} FindPlayerState;/* This is a dummy class that we pass off any outstanding timer references to when we shut down. It has two reasons for existing: 1. Mozilla bug 215163 (affecting versions up to 1.4) means that CHXPlayerBackend can have dangling timer references that prevent a clean shutdown. The CHXTimerFob takes ownership of these references. 2. The timer can release its reference from another thread that can run after NS_PluginShutdown gets called. There's nothing wrong with this per se, but I'm more comfortable if the backend shuts down at the same time as the plugin, rather than sticking around until all timer references are released.*/class CHXTimerFob : public nsIObserver{ NS_DECL_ISUPPORTS CHXTimerFob() { }; virtual ~CHXTimerFob() { }; // nsIObserver methods NS_IMETHOD Observe(nsISupports *pSubject, const char *szTopic, const PRUnichar *pData) { printf("This should not be called\n"); return NS_OK; }};// nsIObserverNS_IMPL_ISUPPORTS1(CHXTimerFob, nsIObserver)// nsIObserverNS_IMPL_ISUPPORTS1(CHXPlayerBackend, nsIObserver) NS_IMETHODIMP CHXPlayerBackend::Observe(nsISupports * /* pSubject */, const char *szTopic, const PRUnichar * /*pData*/){ if(strcmp(szTopic, NS_TIMER_CALLBACK_TOPIC) != 0) { return NS_ERROR_FAILURE; } if(m_bPlayerShutdown) { return NS_ERROR_FAILURE; } return PollForCallbacks();}CHXPlayerBackend::CHXPlayerBackend() : m_bCallbackTimerRunning(FALSE), m_fdApi(-1), m_fdCallback(-1), m_nChildPid(0), m_bPlayerShutdown(PR_FALSE), m_bEmbeddedPlayerOpen(PR_FALSE), m_pCallbackBuf(NULL), m_nCallbackBufLen(0), m_nCallbackBufPos(0), m_pTimer(NULL), m_pObsoleteTimer(NULL), m_pUConv(NULL), m_pPromptService(NULL), m_pMemory(NULL), m_pPlayersList(NULL), m_nPlayerCount(0), m_nMaxPlayers(0){}CHXPlayerBackend::~CHXPlayerBackend(){ if(m_nPlayerCount == 0) { printf("Shutting down with plugins still existing\n"); }}nsresult CHXPlayerBackend::SendMessage(const char *pBuf, int nSize){ ssize_t nPos = 0; ssize_t nResult; fd_set fdsWrite, fdsException; struct timeval timeout; int nDescriptors; nsresult result = NS_OK; if(!m_bEmbeddedPlayerOpen) { return NS_ERROR_FAILURE; } do { FD_ZERO(&fdsWrite); FD_ZERO(&fdsException); FD_SET(m_fdApi, &fdsWrite); FD_SET(m_fdApi, &fdsException); timeout.tv_sec = IPC_TIMEOUT; timeout.tv_usec = 0; nDescriptors = select(m_fdApi + 1, NULL, &fdsWrite, &fdsException, &timeout); if(nDescriptors < 0) { perror("select"); break; } else if(nDescriptors == 0) { /* We timed out. The current ipc protocol doesn't deal with this well, as responses can't be mapped to requests. */ printf("Timed out in SendMessage\n"); result = NS_ERROR_FAILURE; break; } else if(FD_ISSET(m_fdApi, &fdsException)) { /* This should never happen. */ printf("Exception in SendMessage\n"); result = NS_ERROR_FAILURE; break; } else if(FD_ISSET(m_fdApi, &fdsWrite)) { /* We can read */ nResult = write(m_fdApi, pBuf + nPos, nSize - nPos); if(nResult <= 0) { if(nResult < 0) { if((errno != EINTR) && (errno != EAGAIN)) { perror("write"); result = NS_ERROR_FAILURE; } } /* Connection closed */ result = NS_ERROR_FAILURE; CloseEmbeddedPlayer(PR_FALSE); break; } else { nPos += nResult; } } else { /* This is unreachable. */ printf("Unknown state in select()\n"); result = NS_ERROR_FAILURE; break; } } while(nPos < nSize); return result;}nsresult CHXPlayerBackend::ReceiveMessage(char **ppBuf){ ssize_t nPos = 0; ssize_t nResult; fd_set fdsRead, fdsException; struct timeval timeout; int nDescriptors; int nSize = 1024; char *pBuf; nsresult result = NS_ERROR_FAILURE; if(!m_bEmbeddedPlayerOpen) { return NS_ERROR_FAILURE; } pBuf = (char*)malloc(nSize); *ppBuf = pBuf; for(;;) { FD_ZERO(&fdsRead); FD_ZERO(&fdsException); FD_SET(m_fdApi, &fdsRead); FD_SET(m_fdApi, &fdsException); timeout.tv_sec = IPC_TIMEOUT; timeout.tv_usec = 0; nDescriptors = select(m_fdApi + 1, &fdsRead, NULL, &fdsException, &timeout); if(nDescriptors < 0) { if(errno != EINTR) { perror("select"); } break; } else if(nDescriptors == 0) { /* We timed out. The current ipc protocol doesn't deal with this well, as responses can't be mapped to requests. */ printf("Timed out in ReceiveMessage\n"); break; } else if(FD_ISSET(m_fdApi, &fdsException)) { /* This should never happen. */ printf("Exception in ReceiveMessage\n"); break; } else if(FD_ISSET(m_fdApi, &fdsRead)) { /* We can read */ nResult = read(m_fdApi, pBuf + nPos, nSize - nPos); if(nResult <= 0) { if(nResult < 0) { if((errno != EINTR) && (errno != EAGAIN)) { perror("read"); } } /* Connection closed */ CloseEmbeddedPlayer(PR_FALSE); break; } else { char* pNewLine; nPos += nResult; if(nPos >= nSize) { /* We need more buffer space */ nSize *= 2; pBuf = (char*)realloc(pBuf, nSize); } pBuf[nPos] = '\0'; pNewLine = strchr(pBuf, '\n'); if(pNewLine) { if((pNewLine - pBuf) != (nPos - 1)) { /* Newline should have been the last thing we read */ printf("Got data after newline\n"); } result = NS_OK; break; } } } else { /* This is unreachable. */ printf("Unknown state in select()\n"); break; } } if(result == NS_OK) { /* Trim back the buffer to the size we actually used (plus NULL) */ pBuf = (char*)realloc(pBuf, nPos + 1); } else { free(pBuf); *ppBuf = NULL; } return result;}nsresult CHXPlayerBackend::Init(NPP instance){ // Query for services nsIServiceManager *pServiceManager = NULL; nsIComponentManager *pComponentManager = NULL; NPN_GetValue(NULL, NPNVserviceManager, &pServiceManager); nsresult rv; if(!pServiceManager) { /* There are two possibilities here: 1. We are not being used by mozilla 2. We are being used by mozilla, but we were compiled with the wrong version of mozilla. We check for the latter here. */ nsIServiceManager *pUnusable = NULL; NPN_GetValue(NULL, (NPNVariable)(NPNVserviceManager ^ NP_ABI_GCC3_MASK), &pUnusable); if(pUnusable) { /* This is not a fatal error -- we can still run, but callbacks will not function properly. */ ShowError("The HelixPlayer plugin and mozilla were compiled with different versions of gcc.", instance); } } if(pServiceManager) { pServiceManager->GetServiceByContractID("@mozilla.org/embedcomp/prompt-service;1", NS_GET_IID(nsIPromptService),
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -