Merge pull request #2696 from dumganhar/websocket

fixed #1647: Adding WebSocket support for Cpp and JSB [develop]
This commit is contained in:
James Chen 2013-06-02 19:38:51 -07:00
commit cf3b79cbec
33 changed files with 5224 additions and 24 deletions

View File

@ -26,6 +26,8 @@ THE SOFTWARE.
#ifndef __MINGW32__
NS_CC_BEGIN
int gettimeofday(struct timeval * val, struct timezone *)
{
if (val)
@ -39,4 +41,6 @@ int gettimeofday(struct timeval * val, struct timezone *)
return 0;
}
NS_CC_END
#endif // __MINGW32__

View File

@ -87,6 +87,7 @@ THE SOFTWARE.
#include <WinSock2.h>
NS_CC_BEGIN
struct timezone
{
@ -96,6 +97,8 @@ struct timezone
int CC_DLL gettimeofday(struct timeval *, struct timezone *);
NS_CC_END
#else
#include <winsock.h>

View File

@ -48,6 +48,7 @@ GUI/CCScrollView/CCSorting.cpp \
GUI/CCEditBox/CCEditBox.cpp \
GUI/CCEditBox/CCEditBoxImplAndroid.cpp \
network/HttpClient.cpp \
network/WebSocket.cpp \
physics_nodes/CCPhysicsDebugNode.cpp \
physics_nodes/CCPhysicsSprite.cpp \
LocalStorage/LocalStorageAndroid.cpp \
@ -76,6 +77,7 @@ LOCAL_WHOLE_STATIC_LIBRARIES += cocosdenshion_static
LOCAL_WHOLE_STATIC_LIBRARIES += cocos_curl_static
LOCAL_WHOLE_STATIC_LIBRARIES += box2d_static
LOCAL_WHOLE_STATIC_LIBRARIES += chipmunk_static
LOCAL_WHOLE_STATIC_LIBRARIES += libwebsockets_static
LOCAL_CFLAGS += -DCC_ENABLE_CHIPMUNK_INTEGRATION=1
LOCAL_EXPORT_CFLAGS += -DCC_ENABLE_CHIPMUNK_INTEGRATION=1
@ -94,3 +96,4 @@ $(call import-module,CocosDenshion/android)
$(call import-module,cocos2dx/platform/third_party/android/prebuilt/libcurl)
$(call import-module,external/Box2D)
$(call import-module,external/chipmunk)
$(call import-module,external/libwebsockets/android)

View File

@ -0,0 +1,659 @@
/****************************************************************************
Copyright (c) 2010-2013 cocos2d-x.org
Copyright (c) 2013 James Chen
http://www.cocos2d-x.org
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#include "WebSocket.h"
#include <queue>
#include <signal.h>
#include <errno.h>
NS_CC_EXT_BEGIN
class WsMessage
{
public:
WsMessage() : what(0), obj(NULL){}
unsigned int what; // message type
void* obj;
};
/**
* @brief Websocket thread helper, it's used for sending message between UI thread and websocket thread.
*/
class WsThreadHelper : public cocos2d::CCObject
{
public:
WsThreadHelper();
~WsThreadHelper();
// Creates a new thread
bool createThread(const WebSocket& ws);
// Quits sub-thread (websocket thread).
void quitSubThread();
// Schedule callback function
virtual void update(float dt);
// Sends message to UI thread. It's needed to be invoked in sub-thread.
void sendMessageToUIThread(WsMessage *msg);
// Sends message to sub-thread(websocket thread). It's needs to be invoked in UI thread.
void sendMessageToSubThread(WsMessage *msg);
// Waits the sub-thread (websocket thread) to exit,
void joinSubThread();
protected:
friend class WsThreadEntry;
void* wsThreadEntryFunc(void* arg);
private:
std::list<WsMessage*>* _UIWsMessageQueue;
std::list<WsMessage*>* _subThreadWsMessageQueue;
pthread_mutex_t _UIWsMessageQueueMutex;
pthread_mutex_t _subThreadWsMessageQueueMutex;
pthread_t _subThreadInstance;
WebSocket* _ws;
bool _needQuit;
friend class WebSocket;
};
// Wrapper for converting websocket callback from static function to member function of WebSocket class.
class WebSocketCallbackWrapper {
public:
static int onSocketCallback(struct libwebsocket_context *ctx,
struct libwebsocket *wsi,
enum libwebsocket_callback_reasons reason,
void *user, void *in, size_t len)
{
// Gets the user data from context. We know that it's a 'WebSocket' instance.
WebSocket* wsInstance = (WebSocket*)libwebsocket_context_user(ctx);
if (wsInstance)
{
return wsInstance->onSocketCallback(ctx, wsi, reason, user, in, len);
}
return 0;
}
};
// Implementation of WsThreadHelper
WsThreadHelper::WsThreadHelper()
: _ws(NULL)
, _needQuit(false)
{
_UIWsMessageQueue = new std::list<WsMessage*>();
pthread_mutex_init(&_UIWsMessageQueueMutex, NULL);
_subThreadWsMessageQueue = new std::list<WsMessage*>();
pthread_mutex_init(&_subThreadWsMessageQueueMutex, NULL);
CCDirector::sharedDirector()->getScheduler()->scheduleUpdateForTarget(this, 0, false);
}
WsThreadHelper::~WsThreadHelper()
{
CCDirector::sharedDirector()->getScheduler()->unscheduleAllForTarget(this);
pthread_mutex_destroy(&_UIWsMessageQueueMutex);
pthread_mutex_destroy(&_subThreadWsMessageQueueMutex);
delete _UIWsMessageQueue;
delete _subThreadWsMessageQueue;
}
// For converting static function to member function
class WsThreadEntry
{
public:
static void* entry(void* arg)
{
WsThreadHelper* self = static_cast<WsThreadHelper*>(arg);
return self->wsThreadEntryFunc(arg);
}
};
bool WsThreadHelper::createThread(const WebSocket& ws)
{
_ws = const_cast<WebSocket*>(&ws);
pthread_attr_t attr;
pthread_attr_init (&attr);
// pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);
// Creates websocket thread
if (0 == pthread_create(&_subThreadInstance, &attr, WsThreadEntry::entry, this))
{
return true;
}
return false;
}
void WsThreadHelper::quitSubThread()
{
_needQuit = true;
}
void* WsThreadHelper::wsThreadEntryFunc(void* arg)
{
_ws->onSubThreadStarted();
while (!_needQuit)
{
if (_ws->onSubThreadLoop())
{
break;
}
}
_ws->onSubThreadEnded();
return (void*)0;
}
void WsThreadHelper::sendMessageToUIThread(WsMessage *msg)
{
pthread_mutex_lock(&_UIWsMessageQueueMutex);
_UIWsMessageQueue->push_back(msg);
pthread_mutex_unlock(&_UIWsMessageQueueMutex);
}
void WsThreadHelper::sendMessageToSubThread(WsMessage *msg)
{
pthread_mutex_lock(&_subThreadWsMessageQueueMutex);
_subThreadWsMessageQueue->push_back(msg);
pthread_mutex_unlock(&_subThreadWsMessageQueueMutex);
}
void WsThreadHelper::joinSubThread()
{
void* ret = NULL;
pthread_join(_subThreadInstance, &ret);
}
void WsThreadHelper::update(float dt)
{
WsMessage *msg = NULL;
// Returns quickly if no message
pthread_mutex_lock(&_UIWsMessageQueueMutex);
if (0 == _UIWsMessageQueue->size())
{
pthread_mutex_unlock(&_UIWsMessageQueueMutex);
return;
}
// Gets message
msg = *(_UIWsMessageQueue->begin());
_UIWsMessageQueue->pop_front();
pthread_mutex_unlock(&_UIWsMessageQueueMutex);
if (_ws)
{
_ws->onUIThreadReceiveMessage(msg);
}
CC_SAFE_DELETE(msg);
}
enum WS_MSG {
WS_MSG_TO_SUBTRHEAD_SENDING_STRING = 0,
WS_MSG_TO_SUBTRHEAD_SENDING_BINARY,
WS_MSG_TO_SUBTRHEAD_CLOSING,
WS_MSG_TO_UITHREAD_OPEN,
WS_MSG_TO_UITHREAD_MESSAGE,
WS_MSG_TO_UITHREAD_ERROR,
WS_MSG_TO_UITHREAD_CLOSE
};
WebSocket::WebSocket()
: _readyState(kStateConnecting)
, _port(80)
, _wsHelper(NULL)
, _wsInstance(NULL)
, _wsContext(NULL)
, _delegate(NULL)
, _SSLConnection(0)
, _wsProtocols(NULL)
{
}
WebSocket::~WebSocket()
{
close();
CC_SAFE_RELEASE_NULL(_wsHelper);
for (int i = 0; _wsProtocols[i].callback != NULL; ++i) {
CC_SAFE_DELETE_ARRAY(_wsProtocols[i].name);
}
CC_SAFE_DELETE_ARRAY(_wsProtocols);
}
bool WebSocket::init(const Delegate& delegate,
const std::string& url,
const std::vector<std::string>* protocols/* = NULL*/)
{
bool ret = false;
bool useSSL = false;
std::string host = url;
int pos = 0;
int port = 80;
_delegate = const_cast<Delegate*>(&delegate);
//ws://
pos = host.find("ws://");
if (pos == 0){
host.erase(0,5);
}
pos = host.find("wss://");
if (pos == 0)
{
host.erase(0,6);
useSSL = true;
}
pos = host.find(":");
if(pos >= 0){
port = atoi(host.substr(pos+1, host.size()).c_str());
}
pos = host.find("/", pos);
std::string path = "/";
if(pos >= 0){
path += host.substr(pos + 1, host.size());
}
pos = host.find(":");
if(pos >= 0){
host.erase(pos, host.size());
}
_host = host;
_port = port;
_path = path;
_SSLConnection = useSSL ? 1 : 0;
int protocolCount = 0;
if (protocols && protocols->size() > 0)
{
protocolCount = protocols->size();
}
else
{
protocolCount = 1;
}
_wsProtocols = new libwebsocket_protocols[protocolCount+1];
memset(_wsProtocols, 0, sizeof(libwebsocket_protocols)*(protocolCount+1));
if (protocols)
{
int i = 0;
for (std::vector<std::string>::const_iterator iter = protocols->begin(); iter != protocols->end(); ++iter, ++i) {
char* name = new char[(*iter).length()+1];
strcpy(name, (*iter).c_str());
_wsProtocols[i].name = name;
_wsProtocols[i].callback = WebSocketCallbackWrapper::onSocketCallback;
}
}
else
{
char* name = new char[20];
strcpy(name, "default-protocol");
_wsProtocols[0].name = name;
_wsProtocols[0].callback = WebSocketCallbackWrapper::onSocketCallback;
}
// WebSocket thread needs to be invoked at the end of this method.
_wsHelper = new WsThreadHelper();
ret = _wsHelper->createThread(*this);
return ret;
}
void WebSocket::send(const std::string& message)
{
if (_readyState == kStateOpen)
{
// In main thread
WsMessage* msg = new WsMessage();
msg->what = WS_MSG_TO_SUBTRHEAD_SENDING_STRING;
Data* data = new Data();
data->bytes = new char[message.length()+1];
strcpy(data->bytes, message.c_str());
data->len = message.length();
msg->obj = data;
_wsHelper->sendMessageToSubThread(msg);
}
}
void WebSocket::send(const unsigned char* binaryMsg, unsigned int len)
{
CCAssert(binaryMsg != NULL && len > 0, "parameter invalid.");
if (_readyState == kStateOpen)
{
// In main thread
WsMessage* msg = new WsMessage();
msg->what = WS_MSG_TO_SUBTRHEAD_SENDING_BINARY;
Data* data = new Data();
data->bytes = new char[len];
memcpy((void*)data->bytes, (void*)binaryMsg, len);
data->len = len;
msg->obj = data;
_wsHelper->sendMessageToSubThread(msg);
}
}
void WebSocket::close()
{
CCDirector::sharedDirector()->getScheduler()->unscheduleAllForTarget(_wsHelper);
if (_readyState == kStateClosing || _readyState == kStateClosed)
return;
CCLOG("websocket (%p) connection closed by client", this);
_readyState = kStateClosed;
WsMessage* msg = new WsMessage();
msg->what = WS_MSG_TO_SUBTRHEAD_CLOSING;
_wsHelper->sendMessageToSubThread(msg);
_wsHelper->joinSubThread();
// onClose callback needs to be invoked at the end of this method
// since websocket instance may be deleted in 'onClose'.
_delegate->onClose(this);
}
WebSocket::State WebSocket::getReadyState()
{
return _readyState;
}
int WebSocket::onSubThreadLoop()
{
if (_readyState == kStateClosed || _readyState == kStateClosing)
{
libwebsocket_context_destroy(_wsContext);
// return 1 to exit the loop.
return 1;
}
if (_wsContext && _readyState != kStateClosed && _readyState != kStateClosing)
{
libwebsocket_service(_wsContext, 0);
}
// Sleep 50 ms
#ifdef WIN32
Sleep(50);
#else
usleep(50000);
#endif
// return 0 to continue the loop.
return 0;
}
void WebSocket::onSubThreadStarted()
{
struct lws_context_creation_info info;
memset(&info, 0, sizeof info);
/*
* create the websocket context. This tracks open connections and
* knows how to route any traffic and which protocol version to use,
* and if each connection is client or server side.
*
* For this client-only demo, we tell it to not listen on any port.
*/
info.port = CONTEXT_PORT_NO_LISTEN;
info.protocols = _wsProtocols;
#ifndef LWS_NO_EXTENSIONS
info.extensions = libwebsocket_get_internal_extensions();
#endif
info.gid = -1;
info.uid = -1;
info.user = (void*)this;
_wsContext = libwebsocket_create_context(&info);
if(NULL != _wsContext){
_readyState = kStateConnecting;
std::string name;
for (int i = 0; _wsProtocols[i].callback != NULL; ++i) {
name += (_wsProtocols[i].name);
if (_wsProtocols[i+1].callback != NULL)
{
name += ", ";
}
}
_wsInstance = libwebsocket_client_connect(_wsContext, _host.c_str(), _port, _SSLConnection,
_path.c_str(), _host.c_str(), _host.c_str(),
name.c_str(), -1);
}
}
void WebSocket::onSubThreadEnded()
{
}
int WebSocket::onSocketCallback(struct libwebsocket_context *ctx,
struct libwebsocket *wsi,
enum libwebsocket_callback_reasons reason,
void *user, void *in, size_t len)
{
//CCLOG("socket callback for %d reason", reason);
CCAssert(_wsContext == NULL || ctx == _wsContext, "Invalid context.");
CCAssert(_wsInstance == NULL || wsi == NULL || wsi == _wsInstance, "Invaild websocket instance.");
switch (reason)
{
case LWS_CALLBACK_DEL_POLL_FD:
case LWS_CALLBACK_PROTOCOL_DESTROY:
case LWS_CALLBACK_CLIENT_CONNECTION_ERROR:
{
WsMessage* msg = new WsMessage();
if (reason == LWS_CALLBACK_CLIENT_CONNECTION_ERROR
|| (reason == LWS_CALLBACK_PROTOCOL_DESTROY && _readyState == kStateConnecting)
|| (reason == LWS_CALLBACK_DEL_POLL_FD && _readyState == kStateConnecting)
)
{
msg->what = WS_MSG_TO_UITHREAD_ERROR;
_readyState = kStateClosing;
}
else if (reason == LWS_CALLBACK_PROTOCOL_DESTROY && _readyState == kStateClosing)
{
msg->what = WS_MSG_TO_UITHREAD_CLOSE;
}
_wsHelper->sendMessageToUIThread(msg);
}
break;
case LWS_CALLBACK_CLIENT_ESTABLISHED:
{
WsMessage* msg = new WsMessage();
msg->what = WS_MSG_TO_UITHREAD_OPEN;
_readyState = kStateOpen;
/*
* start the ball rolling,
* LWS_CALLBACK_CLIENT_WRITEABLE will come next service
*/
libwebsocket_callback_on_writable(ctx, wsi);
_wsHelper->sendMessageToUIThread(msg);
}
break;
case LWS_CALLBACK_CLIENT_WRITEABLE:
{
pthread_mutex_lock(&_wsHelper->_subThreadWsMessageQueueMutex);
std::list<WsMessage*>::iterator iter = _wsHelper->_subThreadWsMessageQueue->begin();
int bytesWrite = 0;
for (; iter != _wsHelper->_subThreadWsMessageQueue->end(); ++iter) {
WsMessage* subThreadMsg = *iter;
if ( WS_MSG_TO_SUBTRHEAD_SENDING_STRING == subThreadMsg->what
|| WS_MSG_TO_SUBTRHEAD_SENDING_BINARY == subThreadMsg->what)
{
Data* data = (Data*)subThreadMsg->obj;
unsigned char* buf = new unsigned char[LWS_SEND_BUFFER_PRE_PADDING
+ data->len + LWS_SEND_BUFFER_POST_PADDING];
memset(&buf[LWS_SEND_BUFFER_PRE_PADDING], 0, data->len);
memcpy((char*)&buf[LWS_SEND_BUFFER_PRE_PADDING], data->bytes, data->len);
enum libwebsocket_write_protocol writeProtocol;
if (WS_MSG_TO_SUBTRHEAD_SENDING_STRING == subThreadMsg->what)
{
writeProtocol = LWS_WRITE_TEXT;
}
else
{
writeProtocol = LWS_WRITE_BINARY;
}
bytesWrite = libwebsocket_write(wsi, &buf[LWS_SEND_BUFFER_PRE_PADDING], data->len, writeProtocol);
if (bytesWrite < 0) {
CCLOGERROR("%s", "libwebsocket_write error...");
}
if (bytesWrite < data->len) {
CCLOGERROR("Partial write LWS_CALLBACK_CLIENT_WRITEABLE\n");
}
CC_SAFE_DELETE_ARRAY(data->bytes);
CC_SAFE_DELETE(data);
CC_SAFE_DELETE_ARRAY(buf);
}
}
_wsHelper->_subThreadWsMessageQueue->clear();
pthread_mutex_unlock(&_wsHelper->_subThreadWsMessageQueueMutex);
/* get notified as soon as we can write again */
libwebsocket_callback_on_writable(ctx, wsi);
}
break;
case LWS_CALLBACK_CLOSED:
{
CCLOG("%s", "connection closing..");
_wsHelper->quitSubThread();
if (_readyState != kStateClosed)
{
WsMessage* msg = new WsMessage();
_readyState = kStateClosed;
msg->what = WS_MSG_TO_UITHREAD_CLOSE;
_wsHelper->sendMessageToUIThread(msg);
}
}
break;
case LWS_CALLBACK_CLIENT_RECEIVE:
{
if (in && len > 0)
{
WsMessage* msg = new WsMessage();
msg->what = WS_MSG_TO_UITHREAD_MESSAGE;
char* bytes = NULL;
Data* data = new Data();
if (lws_frame_is_binary(wsi))
{
bytes = new char[len];
data->isBinary = true;
}
else
{
bytes = new char[len+1];
bytes[len] = '\0';
data->isBinary = false;
}
memcpy(bytes, in, len);
data->bytes = bytes;
data->len = len;
msg->obj = (void*)data;
_wsHelper->sendMessageToUIThread(msg);
}
}
break;
default:
break;
}
return 0;
}
void WebSocket::onUIThreadReceiveMessage(WsMessage* msg)
{
switch (msg->what) {
case WS_MSG_TO_UITHREAD_OPEN:
{
_delegate->onOpen(this);
}
break;
case WS_MSG_TO_UITHREAD_MESSAGE:
{
Data* data = (Data*)msg->obj;
_delegate->onMessage(this, *data);
CC_SAFE_DELETE_ARRAY(data->bytes);
CC_SAFE_DELETE(data);
}
break;
case WS_MSG_TO_UITHREAD_CLOSE:
{
_delegate->onClose(this);
}
break;
case WS_MSG_TO_UITHREAD_ERROR:
{
// FIXME: The exact error needs to be checked.
WebSocket::ErrorCode err = kErrorConnectionFailure;
_delegate->onError(this, err);
}
break;
default:
break;
}
}
NS_CC_EXT_END

View File

@ -0,0 +1,154 @@
/****************************************************************************
Copyright (c) 2010-2013 cocos2d-x.org
Copyright (c) 2013 James Chen
http://www.cocos2d-x.org
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#ifndef __CC_WEBSOCKET_H__
#define __CC_WEBSOCKET_H__
#include "ExtensionMacros.h"
#include <pthread.h>
#include "cocos2d.h"
#include "libwebsockets.h"
#include <list>
NS_CC_EXT_BEGIN
class WsThreadHelper;
class WsMessage;
class WebSocket
{
public:
WebSocket();
virtual ~WebSocket();
/**
* @brief Data structure for message
*/
struct Data
{
Data():bytes(NULL), len(0), isBinary(false){}
char* bytes;
int len;
bool isBinary;
};
/**
* @brief Errors in websocket
*/
enum ErrorCode
{
kErrorTimeout = 0,
kErrorConnectionFailure,
kErrorUnknown
};
/**
* @brief The delegate class to process websocket events.
*/
class Delegate
{
public:
virtual ~Delegate() {}
virtual void onOpen(WebSocket* ws) = 0;
virtual void onMessage(WebSocket* ws, const Data& data) = 0;
virtual void onClose(WebSocket* ws) = 0;
virtual void onError(WebSocket* ws, const ErrorCode& error) = 0;
};
/**
* @brief The initialized method for websocket.
* It needs to be invoked right after websocket instance is allocated.
* @param delegate The delegate which want to receive event from websocket.
* @param url The URL of websocket server.
* @return true: Success, false: Failure
*/
bool init(const Delegate& delegate,
const std::string& url,
const std::vector<std::string>* protocols = NULL);
/**
* @brief Sends string data to websocket server.
*/
void send(const std::string& message);
/**
* @brief Sends binary data to websocket server.
*/
void send(const unsigned char* binaryMsg, unsigned int len);
/**
* @brief Closes the connection to server.
*/
void close();
/**
* Websocket state
*/
enum State
{
kStateConnecting = 0,
kStateOpen,
kStateClosing,
kStateClosed
};
/**
* @brief Gets current state of connection.
*/
State getReadyState();
private:
virtual void onSubThreadStarted();
virtual int onSubThreadLoop();
virtual void onSubThreadEnded();
virtual void onUIThreadReceiveMessage(WsMessage* msg);
friend class WebSocketCallbackWrapper;
int onSocketCallback(struct libwebsocket_context *ctx,
struct libwebsocket *wsi,
enum libwebsocket_callback_reasons reason,
void *user, void *in, size_t len);
private:
State _readyState;
std::string _host;
unsigned int _port;
std::string _path;
friend class WsThreadHelper;
WsThreadHelper* _wsHelper;
struct libwebsocket* _wsInstance;
struct libwebsocket_context* _wsContext;
Delegate* _delegate;
int _SSLConnection;
libwebsocket_protocols* _wsProtocols;
};
NS_CC_EXT_END
#endif /* defined(__CC_JSB_WEBSOCKET_H__) */

View File

@ -63,7 +63,7 @@
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>$(MSBuildProgramFiles32)\Microsoft SDKs\Windows\v7.1A\include;$(ProjectDir)..\..\external\chipmunk\include\chipmunk;$(ProjectDir)..\..\external\sqlite3\include;$(ProjectDir)..\..\external;$(ProjectDir)..\..\cocos2dx;$(ProjectDir)..\..\cocos2dx\include;$(ProjectDir)..\..\cocos2dx\kazmath\include;$(ProjectDir)..\..\cocos2dx\platform\win32;$(ProjectDir)..\..\cocos2dx\platform\third_party\win32;$(ProjectDir)..\..\cocos2dx\platform\third_party\win32\pthread;$(ProjectDir)..\..\cocos2dx\platform\third_party\win32\OGLES;$(ProjectDir)..\..\cocos2dx\platform\third_party\win32\zlib;$(ProjectDir)..\..\CocosDenshion\include;..\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>$(MSBuildProgramFiles32)\Microsoft SDKs\Windows\v7.1A\include;$(ProjectDir)..\..\external\chipmunk\include\chipmunk;$(ProjectDir)..\..\external\sqlite3\include;$(ProjectDir)..\..\external;$(ProjectDir)..\..\external\libwebsockets\win32\include;$(ProjectDir)..\..\cocos2dx;$(ProjectDir)..\..\cocos2dx\include;$(ProjectDir)..\..\cocos2dx\kazmath\include;$(ProjectDir)..\..\cocos2dx\platform\win32;$(ProjectDir)..\..\cocos2dx\platform\third_party\win32;$(ProjectDir)..\..\cocos2dx\platform\third_party\win32\pthread;$(ProjectDir)..\..\cocos2dx\platform\third_party\win32\OGLES;$(ProjectDir)..\..\cocos2dx\platform\third_party\win32\zlib;$(ProjectDir)..\..\CocosDenshion\include;..\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;_WINDOWS;_DEBUG;_LIB;COCOS2D_DEBUG=1;CC_ENABLE_CHIPMUNK_INTEGRATION=1;_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>true</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
@ -79,7 +79,7 @@
<ClCompile>
<Optimization>MaxSpeed</Optimization>
<IntrinsicFunctions>true</IntrinsicFunctions>
<AdditionalIncludeDirectories>$(MSBuildProgramFiles32)\Microsoft SDKs\Windows\v7.1A\include;$(ProjectDir)..\..\external\chipmunk\include\chipmunk;$(ProjectDir)..\..\external\sqlite3\include;$(ProjectDir)..\..\external;$(ProjectDir)..\..\cocos2dx;$(ProjectDir)..\..\cocos2dx\include;$(ProjectDir)..\..\cocos2dx\kazmath\include;$(ProjectDir)..\..\cocos2dx\platform\win32;$(ProjectDir)..\..\cocos2dx\platform\third_party\win32;$(ProjectDir)..\..\cocos2dx\platform\third_party\win32\pthread;$(ProjectDir)..\..\cocos2dx\platform\third_party\win32\OGLES;$(ProjectDir)..\..\cocos2dx\platform\third_party\win32\zlib;$(ProjectDir)..\..\CocosDenshion\include;..\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>$(MSBuildProgramFiles32)\Microsoft SDKs\Windows\v7.1A\include;$(ProjectDir)..\..\external\chipmunk\include\chipmunk;$(ProjectDir)..\..\external\sqlite3\include;$(ProjectDir)..\..\external;$(ProjectDir)..\..\external\libwebsockets\win32\include;$(ProjectDir)..\..\cocos2dx;$(ProjectDir)..\..\cocos2dx\include;$(ProjectDir)..\..\cocos2dx\kazmath\include;$(ProjectDir)..\..\cocos2dx\platform\win32;$(ProjectDir)..\..\cocos2dx\platform\third_party\win32;$(ProjectDir)..\..\cocos2dx\platform\third_party\win32\pthread;$(ProjectDir)..\..\cocos2dx\platform\third_party\win32\OGLES;$(ProjectDir)..\..\cocos2dx\platform\third_party\win32\zlib;$(ProjectDir)..\..\CocosDenshion\include;..\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;_WINDOWS;NDEBUG;_LIB;CC_ENABLE_CHIPMUNK_INTEGRATION=1;_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>
@ -135,6 +135,7 @@
<ClCompile Include="..\GUI\CCScrollView\CCTableViewCell.cpp" />
<ClCompile Include="..\LocalStorage\LocalStorage.cpp" />
<ClCompile Include="..\network\HttpClient.cpp" />
<ClCompile Include="..\network\Websocket.cpp" />
<ClCompile Include="..\physics_nodes\CCPhysicsDebugNode.cpp" />
<ClCompile Include="..\physics_nodes\CCPhysicsSprite.cpp" />
<ClCompile Include="..\spine\Animation.cpp" />
@ -213,6 +214,7 @@
<ClInclude Include="..\network\HttpClient.h" />
<ClInclude Include="..\network\HttpRequest.h" />
<ClInclude Include="..\network\HttpResponse.h" />
<ClInclude Include="..\network\Websocket.h" />
<ClInclude Include="..\physics_nodes\CCPhysicsDebugNode.h" />
<ClInclude Include="..\physics_nodes\CCPhysicsSprite.h" />
<ClInclude Include="..\spine\Animation.h" />

View File

@ -13,9 +13,6 @@
<Filter Include="GUI\CCScrollView">
<UniqueIdentifier>{46797895-f71d-4ddb-b381-d0884e678d39}</UniqueIdentifier>
</Filter>
<Filter Include="GUI\network">
<UniqueIdentifier>{2a7741ff-87a5-41c8-8e51-d7a1cf0c8e4d}</UniqueIdentifier>
</Filter>
<Filter Include="physics_nodes">
<UniqueIdentifier>{d5806151-7ae1-4fef-af5a-2fa1d1c7377b}</UniqueIdentifier>
</Filter>
@ -31,13 +28,16 @@
<Filter Include="spine">
<UniqueIdentifier>{ff4b5934-99d4-4ea7-9f50-a774192d9ca9}</UniqueIdentifier>
</Filter>
<Filter Include="network">
<UniqueIdentifier>{2a7741ff-87a5-41c8-8e51-d7a1cf0c8e4d}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\GUI\CCScrollView\CCScrollView.cpp">
<Filter>GUI\CCScrollView</Filter>
</ClCompile>
<ClCompile Include="..\network\HttpClient.cpp">
<Filter>GUI\network</Filter>
<Filter>network</Filter>
</ClCompile>
<ClCompile Include="..\GUI\CCScrollView\CCSorting.cpp">
<Filter>GUI\CCScrollView</Filter>
@ -231,6 +231,9 @@
<ClCompile Include="..\spine\spine-cocos2dx.cpp">
<Filter>spine</Filter>
</ClCompile>
<ClCompile Include="..\network\Websocket.cpp">
<Filter>network</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\GUI\CCScrollView\CCScrollView.h">
@ -239,13 +242,13 @@
<ClInclude Include="..\cocos-ext.h" />
<ClInclude Include="..\ExtensionMacros.h" />
<ClInclude Include="..\network\HttpClient.h">
<Filter>GUI\network</Filter>
<Filter>network</Filter>
</ClInclude>
<ClInclude Include="..\network\HttpRequest.h">
<Filter>GUI\network</Filter>
<Filter>network</Filter>
</ClInclude>
<ClInclude Include="..\network\HttpResponse.h">
<Filter>GUI\network</Filter>
<Filter>network</Filter>
</ClInclude>
<ClInclude Include="..\GUI\CCScrollView\CCSorting.h">
<Filter>GUI\CCScrollView</Filter>
@ -460,5 +463,8 @@
<ClInclude Include="..\spine\spine.h">
<Filter>spine</Filter>
</ClInclude>
<ClInclude Include="..\network\Websocket.h">
<Filter>network</Filter>
</ClInclude>
</ItemGroup>
</Project>

View File

@ -0,0 +1,10 @@
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := libwebsockets_static
LOCAL_MODULE_FILENAME := libwebsockets_static
LOCAL_SRC_FILES := ./lib/$(TARGET_ARCH_ABI)/libwebsockets.a
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include
LOCAL_CPPFLAGS := -D__STDC_LIMIT_MACROS=1
LOCAL_EXPORT_CPPFLAGS := -D__STDC_LIMIT_MACROS=1
include $(PREBUILT_STATIC_LIBRARY)

View File

@ -0,0 +1,993 @@
/*
* libwebsockets - small server side websockets and web server implementation
*
* Copyright (C) 2010-2013 Andy Green <andy@warmcat.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation:
* version 2.1 of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
#ifndef __LIBWEBSOCKET_H__
#define __LIBWEBSOCKET_H__
#ifdef __cplusplus
extern "C" {
#include <cstddef>
#endif
#ifdef WIN32
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stddef.h>
#include "../win32port/win32helpers/websock-w32.h"
#include "../win32port/win32helpers/gettimeofday.h"
#define strcasecmp stricmp
#define getdtablesize() 30000
typedef int ssize_t;
#define LWS_VISIBLE
#ifdef LWS_DLL
#ifdef LWS_INTERNAL
#define LWS_EXTERN extern __declspec(dllexport)
#else
#define LWS_EXTERN extern __declspec(dllimport)
#endif
#else
#define LWS_EXTERN
#endif
#else // NOT WIN32
#include <poll.h>
#include <unistd.h>
#if defined(__GNUC__)
#define LWS_VISIBLE __attribute__((visibility("default")))
#else
#define LWS_VISIBLE
#endif
#endif
#include <assert.h>
#ifndef LWS_EXTERN
#define LWS_EXTERN extern
#endif
#define CONTEXT_PORT_NO_LISTEN 0
#define MAX_MUX_RECURSION 2
enum lws_log_levels {
LLL_ERR = 1 << 0,
LLL_WARN = 1 << 1,
LLL_NOTICE = 1 << 2,
LLL_INFO = 1 << 3,
LLL_DEBUG = 1 << 4,
LLL_PARSER = 1 << 5,
LLL_HEADER = 1 << 6,
LLL_EXT = 1 << 7,
LLL_CLIENT = 1 << 8,
LLL_LATENCY = 1 << 9,
LLL_COUNT = 10 /* set to count of valid flags */
};
LWS_VISIBLE LWS_EXTERN void _lws_log(int filter, const char *format, ...);
/* notice, warn and log are always compiled in */
#define lwsl_notice(...) _lws_log(LLL_NOTICE, __VA_ARGS__)
#define lwsl_warn(...) _lws_log(LLL_WARN, __VA_ARGS__)
#define lwsl_err(...) _lws_log(LLL_ERR, __VA_ARGS__)
/*
* weaker logging can be deselected at configure time using --disable-debug
* that gets rid of the overhead of checking while keeping _warn and _err
* active
*/
#ifdef _DEBUG
#define lwsl_info(...) _lws_log(LLL_INFO, __VA_ARGS__)
#define lwsl_debug(...) _lws_log(LLL_DEBUG, __VA_ARGS__)
#define lwsl_parser(...) _lws_log(LLL_PARSER, __VA_ARGS__)
#define lwsl_header(...) _lws_log(LLL_HEADER, __VA_ARGS__)
#define lwsl_ext(...) _lws_log(LLL_EXT, __VA_ARGS__)
#define lwsl_client(...) _lws_log(LLL_CLIENT, __VA_ARGS__)
#define lwsl_latency(...) _lws_log(LLL_LATENCY, __VA_ARGS__)
LWS_VISIBLE LWS_EXTERN void lwsl_hexdump(void *buf, size_t len);
#else /* no debug */
#define lwsl_info(...)
#define lwsl_debug(...)
#define lwsl_parser(...)
#define lwsl_header(...)
#define lwsl_ext(...)
#define lwsl_client(...)
#define lwsl_latency(...)
#define lwsl_hexdump(a, b)
#endif
enum libwebsocket_context_options {
LWS_SERVER_OPTION_REQUIRE_VALID_OPENSSL_CLIENT_CERT = 2,
LWS_SERVER_OPTION_SKIP_SERVER_CANONICAL_NAME = 4,
};
enum libwebsocket_callback_reasons {
LWS_CALLBACK_ESTABLISHED,
LWS_CALLBACK_CLIENT_CONNECTION_ERROR,
LWS_CALLBACK_CLIENT_FILTER_PRE_ESTABLISH,
LWS_CALLBACK_CLIENT_ESTABLISHED,
LWS_CALLBACK_CLOSED,
LWS_CALLBACK_RECEIVE,
LWS_CALLBACK_CLIENT_RECEIVE,
LWS_CALLBACK_CLIENT_RECEIVE_PONG,
LWS_CALLBACK_CLIENT_WRITEABLE,
LWS_CALLBACK_SERVER_WRITEABLE,
LWS_CALLBACK_HTTP,
LWS_CALLBACK_HTTP_FILE_COMPLETION,
LWS_CALLBACK_HTTP_WRITEABLE,
LWS_CALLBACK_FILTER_NETWORK_CONNECTION,
LWS_CALLBACK_FILTER_PROTOCOL_CONNECTION,
LWS_CALLBACK_OPENSSL_LOAD_EXTRA_CLIENT_VERIFY_CERTS,
LWS_CALLBACK_OPENSSL_LOAD_EXTRA_SERVER_VERIFY_CERTS,
LWS_CALLBACK_OPENSSL_PERFORM_CLIENT_CERT_VERIFICATION,
LWS_CALLBACK_CLIENT_APPEND_HANDSHAKE_HEADER,
LWS_CALLBACK_CONFIRM_EXTENSION_OKAY,
LWS_CALLBACK_CLIENT_CONFIRM_EXTENSION_SUPPORTED,
LWS_CALLBACK_PROTOCOL_INIT,
LWS_CALLBACK_PROTOCOL_DESTROY,
/* external poll() management support */
LWS_CALLBACK_ADD_POLL_FD,
LWS_CALLBACK_DEL_POLL_FD,
LWS_CALLBACK_SET_MODE_POLL_FD,
LWS_CALLBACK_CLEAR_MODE_POLL_FD,
};
#ifndef LWS_NO_EXTENSIONS
enum libwebsocket_extension_callback_reasons {
LWS_EXT_CALLBACK_SERVER_CONTEXT_CONSTRUCT,
LWS_EXT_CALLBACK_CLIENT_CONTEXT_CONSTRUCT,
LWS_EXT_CALLBACK_SERVER_CONTEXT_DESTRUCT,
LWS_EXT_CALLBACK_CLIENT_CONTEXT_DESTRUCT,
LWS_EXT_CALLBACK_CONSTRUCT,
LWS_EXT_CALLBACK_CLIENT_CONSTRUCT,
LWS_EXT_CALLBACK_CHECK_OK_TO_REALLY_CLOSE,
LWS_EXT_CALLBACK_CHECK_OK_TO_PROPOSE_EXTENSION,
LWS_EXT_CALLBACK_DESTROY,
LWS_EXT_CALLBACK_DESTROY_ANY_WSI_CLOSING,
LWS_EXT_CALLBACK_ANY_WSI_ESTABLISHED,
LWS_EXT_CALLBACK_PACKET_RX_PREPARSE,
LWS_EXT_CALLBACK_PACKET_TX_PRESEND,
LWS_EXT_CALLBACK_PACKET_TX_DO_SEND,
LWS_EXT_CALLBACK_HANDSHAKE_REPLY_TX,
LWS_EXT_CALLBACK_FLUSH_PENDING_TX,
LWS_EXT_CALLBACK_EXTENDED_PAYLOAD_RX,
LWS_EXT_CALLBACK_CAN_PROXY_CLIENT_CONNECTION,
LWS_EXT_CALLBACK_1HZ,
LWS_EXT_CALLBACK_REQUEST_ON_WRITEABLE,
LWS_EXT_CALLBACK_IS_WRITEABLE,
LWS_EXT_CALLBACK_PAYLOAD_TX,
LWS_EXT_CALLBACK_PAYLOAD_RX,
};
#endif
enum libwebsocket_write_protocol {
LWS_WRITE_TEXT,
LWS_WRITE_BINARY,
LWS_WRITE_CONTINUATION,
LWS_WRITE_HTTP,
/* special 04+ opcodes */
LWS_WRITE_CLOSE,
LWS_WRITE_PING,
LWS_WRITE_PONG,
/* flags */
LWS_WRITE_NO_FIN = 0x40,
/*
* client packet payload goes out on wire unmunged
* only useful for security tests since normal servers cannot
* decode the content if used
*/
LWS_WRITE_CLIENT_IGNORE_XOR_MASK = 0x80
};
/*
* you need these to look at headers that have been parsed if using the
* LWS_CALLBACK_FILTER_CONNECTION callback. If a header from the enum
* list below is absent, .token = NULL and token_len = 0. Otherwise .token
* points to .token_len chars containing that header content.
*/
struct lws_tokens {
char *token;
int token_len;
};
enum lws_token_indexes {
WSI_TOKEN_GET_URI,
WSI_TOKEN_HOST,
WSI_TOKEN_CONNECTION,
WSI_TOKEN_KEY1,
WSI_TOKEN_KEY2,
WSI_TOKEN_PROTOCOL,
WSI_TOKEN_UPGRADE,
WSI_TOKEN_ORIGIN,
WSI_TOKEN_DRAFT,
WSI_TOKEN_CHALLENGE,
/* new for 04 */
WSI_TOKEN_KEY,
WSI_TOKEN_VERSION,
WSI_TOKEN_SWORIGIN,
/* new for 05 */
WSI_TOKEN_EXTENSIONS,
/* client receives these */
WSI_TOKEN_ACCEPT,
WSI_TOKEN_NONCE,
WSI_TOKEN_HTTP,
WSI_TOKEN_MUXURL,
/* use token storage to stash these */
_WSI_TOKEN_CLIENT_SENT_PROTOCOLS,
_WSI_TOKEN_CLIENT_PEER_ADDRESS,
_WSI_TOKEN_CLIENT_URI,
_WSI_TOKEN_CLIENT_HOST,
_WSI_TOKEN_CLIENT_ORIGIN,
/* always last real token index*/
WSI_TOKEN_COUNT,
/* parser state additions */
WSI_TOKEN_NAME_PART,
WSI_TOKEN_SKIPPING,
WSI_TOKEN_SKIPPING_SAW_CR,
WSI_PARSING_COMPLETE,
WSI_INIT_TOKEN_MUXURL,
};
/*
* From RFC 6455
1000
1000 indicates a normal closure, meaning that the purpose for
which the connection was established has been fulfilled.
1001
1001 indicates that an endpoint is "going away", such as a server
going down or a browser having navigated away from a page.
1002
1002 indicates that an endpoint is terminating the connection due
to a protocol error.
1003
1003 indicates that an endpoint is terminating the connection
because it has received a type of data it cannot accept (e.g., an
endpoint that understands only text data MAY send this if it
receives a binary message).
1004
Reserved. The specific meaning might be defined in the future.
1005
1005 is a reserved value and MUST NOT be set as a status code in a
Close control frame by an endpoint. It is designated for use in
applications expecting a status code to indicate that no status
code was actually present.
1006
1006 is a reserved value and MUST NOT be set as a status code in a
Close control frame by an endpoint. It is designated for use in
applications expecting a status code to indicate that the
connection was closed abnormally, e.g., without sending or
receiving a Close control frame.
1007
1007 indicates that an endpoint is terminating the connection
because it has received data within a message that was not
consistent with the type of the message (e.g., non-UTF-8 [RFC3629]
data within a text message).
1008
1008 indicates that an endpoint is terminating the connection
because it has received a message that violates its policy. This
is a generic status code that can be returned when there is no
other more suitable status code (e.g., 1003 or 1009) or if there
is a need to hide specific details about the policy.
1009
1009 indicates that an endpoint is terminating the connection
because it has received a message that is too big for it to
process.
1010
1010 indicates that an endpoint (client) is terminating the
connection because it has expected the server to negotiate one or
more extension, but the server didn't return them in the response
message of the WebSocket handshake. The list of extensions that
are needed SHOULD appear in the /reason/ part of the Close frame.
Note that this status code is not used by the server, because it
can fail the WebSocket handshake instead.
1011
1011 indicates that a server is terminating the connection because
it encountered an unexpected condition that prevented it from
fulfilling the request.
1015
1015 is a reserved value and MUST NOT be set as a status code in a
Close control frame by an endpoint. It is designated for use in
applications expecting a status code to indicate that the
connection was closed due to a failure to perform a TLS handshake
(e.g., the server certificate can't be verified).
*/
enum lws_close_status {
LWS_CLOSE_STATUS_NOSTATUS = 0,
LWS_CLOSE_STATUS_NORMAL = 1000,
LWS_CLOSE_STATUS_GOINGAWAY = 1001,
LWS_CLOSE_STATUS_PROTOCOL_ERR = 1002,
LWS_CLOSE_STATUS_UNACCEPTABLE_OPCODE = 1003,
LWS_CLOSE_STATUS_RESERVED = 1004,
LWS_CLOSE_STATUS_NO_STATUS = 1005,
LWS_CLOSE_STATUS_ABNORMAL_CLOSE = 1006,
LWS_CLOSE_STATUS_INVALID_PAYLOAD = 1007,
LWS_CLOSE_STATUS_POLICY_VIOLATION = 1008,
LWS_CLOSE_STATUS_MESSAGE_TOO_LARGE = 1009,
LWS_CLOSE_STATUS_EXTENSION_REQUIRED = 1010,
LWS_CLOSE_STATUS_UNEXPECTED_CONDITION = 1011,
LWS_CLOSE_STATUS_TLS_FAILURE = 1015,
};
struct libwebsocket;
struct libwebsocket_context;
/* needed even with extensions disabled for create context */
struct libwebsocket_extension;
/**
* callback_function() - User server actions
* @context: Websockets context
* @wsi: Opaque websocket instance pointer
* @reason: The reason for the call
* @user: Pointer to per-session user data allocated by library
* @in: Pointer used for some callback reasons
* @len: Length set for some callback reasons
*
* This callback is the way the user controls what is served. All the
* protocol detail is hidden and handled by the library.
*
* For each connection / session there is user data allocated that is
* pointed to by "user". You set the size of this user data area when
* the library is initialized with libwebsocket_create_server.
*
* You get an opportunity to initialize user data when called back with
* LWS_CALLBACK_ESTABLISHED reason.
*
* LWS_CALLBACK_ESTABLISHED: after the server completes a handshake with
* an incoming client
*
* LWS_CALLBACK_CLIENT_CONNECTION_ERROR: the request client connection has
* been unable to complete a handshake with the remote server
*
* LWS_CALLBACK_CLIENT_FILTER_PRE_ESTABLISH: this is the last chance for the
* client user code to examine the http headers
* and decide to reject the connection. If the
* content in the headers is interesting to the
* client (url, etc) it needs to copy it out at
* this point since it will be destroyed before
* the CLIENT_ESTABLISHED call
*
* LWS_CALLBACK_CLIENT_ESTABLISHED: after your client connection completed
* a handshake with the remote server
*
* LWS_CALLBACK_CLOSED: when the websocket session ends
*
* LWS_CALLBACK_RECEIVE: data has appeared for this server endpoint from a
* remote client, it can be found at *in and is
* len bytes long
*
* LWS_CALLBACK_CLIENT_RECEIVE_PONG: if you elected to see PONG packets,
* they appear with this callback reason. PONG
* packets only exist in 04+ protocol
*
* LWS_CALLBACK_CLIENT_RECEIVE: data has appeared from the server for the
* client connection, it can be found at *in and
* is len bytes long
*
* LWS_CALLBACK_HTTP: an http request has come from a client that is not
* asking to upgrade the connection to a websocket
* one. This is a chance to serve http content,
* for example, to send a script to the client
* which will then open the websockets connection.
* @in points to the URI path requested and
* libwebsockets_serve_http_file() makes it very
* simple to send back a file to the client.
* Normally after sending the file you are done
* with the http connection, since the rest of the
* activity will come by websockets from the script
* that was delivered by http, so you will want to
* return 1; to close and free up the connection.
* That's important because it uses a slot in the
* total number of client connections allowed set
* by MAX_CLIENTS.
*
* LWS_CALLBACK_HTTP_WRITEABLE: you can write more down the http protocol
* link now.
*
* LWS_CALLBACK_HTTP_FILE_COMPLETION: a file requested to be send down
* http link has completed.
*
* LWS_CALLBACK_CLIENT_WRITEABLE:
* LWS_CALLBACK_SERVER_WRITEABLE: If you call
* libwebsocket_callback_on_writable() on a connection, you will
* get one of these callbacks coming when the connection socket
* is able to accept another write packet without blocking.
* If it already was able to take another packet without blocking,
* you'll get this callback at the next call to the service loop
* function. Notice that CLIENTs get LWS_CALLBACK_CLIENT_WRITEABLE
* and servers get LWS_CALLBACK_SERVER_WRITEABLE.
*
* LWS_CALLBACK_FILTER_NETWORK_CONNECTION: called when a client connects to
* the server at network level; the connection is accepted but then
* passed to this callback to decide whether to hang up immediately
* or not, based on the client IP. @in contains the connection
* socket's descriptor. Return non-zero to terminate
* the connection before sending or receiving anything.
* Because this happens immediately after the network connection
* from the client, there's no websocket protocol selected yet so
* this callback is issued only to protocol 0.
*
* LWS_CALLBACK_FILTER_PROTOCOL_CONNECTION: called when the handshake has
* been received and parsed from the client, but the response is
* not sent yet. Return non-zero to disallow the connection.
* @user is a pointer to an array of struct lws_tokens, you can
* use the header enums lws_token_indexes from libwebsockets.h
* to check for and read the supported header presence and
* content before deciding to allow the handshake to proceed or
* to kill the connection.
*
* LWS_CALLBACK_OPENSSL_LOAD_EXTRA_CLIENT_VERIFY_CERTS: if configured for
* including OpenSSL support, this callback allows your user code
* to perform extra SSL_CTX_load_verify_locations() or similar
* calls to direct OpenSSL where to find certificates the client
* can use to confirm the remote server identity. @user is the
* OpenSSL SSL_CTX*
*
* LWS_CALLBACK_OPENSSL_LOAD_EXTRA_SERVER_VERIFY_CERTS: if configured for
* including OpenSSL support, this callback allows your user code
* to load extra certifcates into the server which allow it to
* verify the validity of certificates returned by clients. @user
* is the server's OpenSSL SSL_CTX*
*
* LWS_CALLBACK_OPENSSL_PERFORM_CLIENT_CERT_VERIFICATION: if the
* libwebsockets context was created with the option
* LWS_SERVER_OPTION_REQUIRE_VALID_OPENSSL_CLIENT_CERT, then this
* callback is generated during OpenSSL verification of the cert
* sent from the client. It is sent to protocol[0] callback as
* no protocol has been negotiated on the connection yet.
* Notice that the libwebsockets context and wsi are both NULL
* during this callback. See
* http://www.openssl.org/docs/ssl/SSL_CTX_set_verify.html
* to understand more detail about the OpenSSL callback that
* generates this libwebsockets callback and the meanings of the
* arguments passed. In this callback, @user is the x509_ctx,
* @in is the ssl pointer and @len is preverify_ok
* Notice that this callback maintains libwebsocket return
* conventions, return 0 to mean the cert is OK or 1 to fail it.
* This also means that if you don't handle this callback then
* the default callback action of returning 0 allows the client
* certificates.
*
* LWS_CALLBACK_CLIENT_APPEND_HANDSHAKE_HEADER: this callback happens
* when a client handshake is being compiled. @user is NULL,
* @in is a char **, it's pointing to a char * which holds the
* next location in the header buffer where you can add
* headers, and @len is the remaining space in the header buffer,
* which is typically some hundreds of bytes. So, to add a canned
* cookie, your handler code might look similar to:
*
* char **p = (char **)in;
*
* if (len < 100)
* return 1;
*
* *p += sprintf(*p, "Cookie: a=b\x0d\x0a");
*
* return 0;
*
* Notice if you add anything, you just have to take care about
* the CRLF on the line you added. Obviously this callback is
* optional, if you don't handle it everything is fine.
*
* Notice the callback is coming to protocols[0] all the time,
* because there is no specific protocol handshook yet.
*
* LWS_CALLBACK_CONFIRM_EXTENSION_OKAY: When the server handshake code
* sees that it does support a requested extension, before
* accepting the extension by additing to the list sent back to
* the client it gives this callback just to check that it's okay
* to use that extension. It calls back to the requested protocol
* and with @in being the extension name, @len is 0 and @user is
* valid. Note though at this time the ESTABLISHED callback hasn't
* happened yet so if you initialize @user content there, @user
* content during this callback might not be useful for anything.
* Notice this callback comes to protocols[0].
*
* LWS_CALLBACK_CLIENT_CONFIRM_EXTENSION_SUPPORTED: When a client
* connection is being prepared to start a handshake to a server,
* each supported extension is checked with protocols[0] callback
* with this reason, giving the user code a chance to suppress the
* claim to support that extension by returning non-zero. If
* unhandled, by default 0 will be returned and the extension
* support included in the header to the server. Notice this
* callback comes to protocols[0].
*
* LWS_CALLBACK_PROTOCOL_INIT: One-time call per protocol so it can
* do initial setup / allocations etc
*
* LWS_CALLBACK_PROTOCOL_DESTROY: One-time call per protocol indicating
* this protocol won't get used at all after this callback, the
* context is getting destroyed. Take the opportunity to
* deallocate everything that was allocated by the protocol.
*
* The next four reasons are optional and only need taking care of if you
* will be integrating libwebsockets sockets into an external polling
* array.
*
* LWS_CALLBACK_ADD_POLL_FD: libwebsocket deals with its poll() loop
* internally, but in the case you are integrating with another
* server you will need to have libwebsocket sockets share a
* polling array with the other server. This and the other
* POLL_FD related callbacks let you put your specialized
* poll array interface code in the callback for protocol 0, the
* first protocol you support, usually the HTTP protocol in the
* serving case. This callback happens when a socket needs to be
* added to the polling loop: @in contains the fd, and
* @len is the events bitmap (like, POLLIN). If you are using the
* internal polling loop (the "service" callback), you can just
* ignore these callbacks.
*
* LWS_CALLBACK_DEL_POLL_FD: This callback happens when a socket descriptor
* needs to be removed from an external polling array. @in is
* the socket desricptor. If you are using the internal polling
* loop, you can just ignore it.
*
* LWS_CALLBACK_SET_MODE_POLL_FD: This callback happens when libwebsockets
* wants to modify the events for the socket descriptor in @in.
* The handler should OR @len on to the events member of the pollfd
* struct for this socket descriptor. If you are using the
* internal polling loop, you can just ignore it.
*
* LWS_CALLBACK_CLEAR_MODE_POLL_FD: This callback occurs when libwebsockets
* wants to modify the events for the socket descriptor in @in.
* The handler should AND ~@len on to the events member of the
* pollfd struct for this socket descriptor. If you are using the
* internal polling loop, you can just ignore it.
*/
LWS_VISIBLE LWS_EXTERN int callback(struct libwebsocket_context *context,
struct libwebsocket *wsi,
enum libwebsocket_callback_reasons reason, void *user,
void *in, size_t len);
typedef int (callback_function)(struct libwebsocket_context *context,
struct libwebsocket *wsi,
enum libwebsocket_callback_reasons reason, void *user,
void *in, size_t len);
#ifndef LWS_NO_EXTENSIONS
/**
* extension_callback_function() - Hooks to allow extensions to operate
* @context: Websockets context
* @ext: This extension
* @wsi: Opaque websocket instance pointer
* @reason: The reason for the call
* @user: Pointer to per-session user data allocated by library
* @in: Pointer used for some callback reasons
* @len: Length set for some callback reasons
*
* Each extension that is active on a particular connection receives
* callbacks during the connection lifetime to allow the extension to
* operate on websocket data and manage itself.
*
* Libwebsockets takes care of allocating and freeing "user" memory for
* each active extension on each connection. That is what is pointed to
* by the @user parameter.
*
* LWS_EXT_CALLBACK_CONSTRUCT: called when the server has decided to
* select this extension from the list provided by the client,
* just before the server will send back the handshake accepting
* the connection with this extension active. This gives the
* extension a chance to initialize its connection context found
* in @user.
*
* LWS_EXT_CALLBACK_CLIENT_CONSTRUCT: same as LWS_EXT_CALLBACK_CONSTRUCT
* but called when client is instantiating this extension. Some
* extensions will work the same on client and server side and then
* you can just merge handlers for both CONSTRUCTS.
*
* LWS_EXT_CALLBACK_DESTROY: called when the connection the extension was
* being used on is about to be closed and deallocated. It's the
* last chance for the extension to deallocate anything it has
* allocated in the user data (pointed to by @user) before the
* user data is deleted. This same callback is used whether you
* are in client or server instantiation context.
*
* LWS_EXT_CALLBACK_PACKET_RX_PREPARSE: when this extension was active on
* a connection, and a packet of data arrived at the connection,
* it is passed to this callback to give the extension a chance to
* change the data, eg, decompress it. @user is pointing to the
* extension's private connection context data, @in is pointing
* to an lws_tokens struct, it consists of a char * pointer called
* token, and an int called token_len. At entry, these are
* set to point to the received buffer and set to the content
* length. If the extension will grow the content, it should use
* a new buffer allocated in its private user context data and
* set the pointed-to lws_tokens members to point to its buffer.
*
* LWS_EXT_CALLBACK_PACKET_TX_PRESEND: this works the same way as
* LWS_EXT_CALLBACK_PACKET_RX_PREPARSE above, except it gives the
* extension a chance to change websocket data just before it will
* be sent out. Using the same lws_token pointer scheme in @in,
* the extension can change the buffer and the length to be
* transmitted how it likes. Again if it wants to grow the
* buffer safely, it should copy the data into its own buffer and
* set the lws_tokens token pointer to it.
*/
LWS_VISIBLE LWS_EXTERN int extension_callback(struct libwebsocket_context *context,
struct libwebsocket_extension *ext,
struct libwebsocket *wsi,
enum libwebsocket_extension_callback_reasons reason,
void *user, void *in, size_t len);
typedef int (extension_callback_function)(struct libwebsocket_context *context,
struct libwebsocket_extension *ext,
struct libwebsocket *wsi,
enum libwebsocket_extension_callback_reasons reason,
void *user, void *in, size_t len);
#endif
/**
* struct libwebsocket_protocols - List of protocols and handlers server
* supports.
* @name: Protocol name that must match the one given in the client
* Javascript new WebSocket(url, 'protocol') name
* @callback: The service callback used for this protocol. It allows the
* service action for an entire protocol to be encapsulated in
* the protocol-specific callback
* @per_session_data_size: Each new connection using this protocol gets
* this much memory allocated on connection establishment and
* freed on connection takedown. A pointer to this per-connection
* allocation is passed into the callback in the 'user' parameter
* @rx_buffer_size: if you want atomic frames delivered to the callback, you
* should set this to the size of the biggest legal frame that
* you support. If the frame size is exceeded, there is no
* error, but the buffer will spill to the user callback when
* full, which you can detect by using
* libwebsockets_remaining_packet_payload(). Notice that you
* just talk about frame size here, the LWS_SEND_BUFFER_PRE_PADDING
* and post-padding are automatically also allocated on top.
* @owning_server: the server init call fills in this opaque pointer when
* registering this protocol with the server.
* @protocol_index: which protocol we are starting from zero
*
* This structure represents one protocol supported by the server. An
* array of these structures is passed to libwebsocket_create_server()
* allows as many protocols as you like to be handled by one server.
*/
struct libwebsocket_protocols {
const char *name;
callback_function *callback;
size_t per_session_data_size;
size_t rx_buffer_size;
/*
* below are filled in on server init and can be left uninitialized,
* no need for user to use them directly either
*/
struct libwebsocket_context *owning_server;
int protocol_index;
};
#ifndef LWS_NO_EXTENSIONS
/**
* struct libwebsocket_extension - An extension we know how to cope with
*
* @name: Formal extension name, eg, "deflate-stream"
* @callback: Service callback
* @per_session_data_size: Libwebsockets will auto-malloc this much
* memory for the use of the extension, a pointer
* to it comes in the @user callback parameter
* @per_context_private_data: Optional storage for this extension that
* is per-context, so it can track stuff across
* all sessions, etc, if it wants
*/
struct libwebsocket_extension {
const char *name;
extension_callback_function *callback;
size_t per_session_data_size;
void *per_context_private_data;
};
#endif
/**
* struct lws_context_creation_info: parameters to create context with
*
* @port: Port to listen on... you can use 0 to suppress listening on
* any port, that's what you want if you are not running a
* websocket server at all but just using it as a client
* @iface: NULL to bind the listen socket to all interfaces, or the
* interface name, eg, "eth2"
* @protocols: Array of structures listing supported protocols and a protocol-
* specific callback for each one. The list is ended with an
* entry that has a NULL callback pointer.
* It's not const because we write the owning_server member
* @extensions: NULL or array of libwebsocket_extension structs listing the
* extensions this context supports. If you configured with
* --without-extensions, you should give NULL here.
* @ssl_cert_filepath: If libwebsockets was compiled to use ssl, and you want
* to listen using SSL, set to the filepath to fetch the
* server cert from, otherwise NULL for unencrypted
* @ssl_private_key_filepath: filepath to private key if wanting SSL mode,
* else ignored
* @ssl_ca_filepath: CA certificate filepath or NULL
* @ssl_cipher_list: List of valid ciphers to use (eg,
* "RC4-MD5:RC4-SHA:AES128-SHA:AES256-SHA:HIGH:!DSS:!aNULL"
* or you can leave it as NULL to get "DEFAULT"
* @gid: group id to change to after setting listen socket, or -1.
* @uid: user id to change to after setting listen socket, or -1.
* @options: 0, or LWS_SERVER_OPTION_DEFEAT_CLIENT_MASK
* @user: optional user pointer that can be recovered via the context
* pointer using libwebsocket_context_user
* @ka_time: 0 for no keepalive, otherwise apply this keepalive timeout to
* all libwebsocket sockets, client or server
* @ka_probes: if ka_time was nonzero, after the timeout expires how many
* times to try to get a response from the peer before giving up
* and killing the connection
* @ka_interval: if ka_time was nonzero, how long to wait before each ka_probes
* attempt
*/
struct lws_context_creation_info {
int port;
const char *iface;
struct libwebsocket_protocols *protocols;
struct libwebsocket_extension *extensions;
const char *ssl_cert_filepath;
const char *ssl_private_key_filepath;
const char *ssl_ca_filepath;
const char *ssl_cipher_list;
int gid;
int uid;
unsigned int options;
void *user;
int ka_time;
int ka_probes;
int ka_interval;
};
LWS_VISIBLE LWS_EXTERN
void lws_set_log_level(int level,
void (*log_emit_function)(int level, const char *line));
LWS_VISIBLE LWS_EXTERN void
lwsl_emit_syslog(int level, const char *line);
LWS_VISIBLE LWS_EXTERN struct libwebsocket_context *
libwebsocket_create_context(struct lws_context_creation_info *info);
LWS_VISIBLE LWS_EXTERN void
libwebsocket_context_destroy(struct libwebsocket_context *context);
LWS_VISIBLE LWS_EXTERN int
libwebsocket_service(struct libwebsocket_context *context, int timeout_ms);
LWS_VISIBLE LWS_EXTERN int
libwebsocket_service_fd(struct libwebsocket_context *context,
struct pollfd *pollfd);
LWS_VISIBLE LWS_EXTERN void *
libwebsocket_context_user(struct libwebsocket_context *context);
/*
* IMPORTANT NOTICE!
*
* When sending with websocket protocol (LWS_WRITE_TEXT or LWS_WRITE_BINARY)
* the send buffer has to have LWS_SEND_BUFFER_PRE_PADDING bytes valid BEFORE
* buf, and LWS_SEND_BUFFER_POST_PADDING bytes valid AFTER (buf + len).
*
* This allows us to add protocol info before and after the data, and send as
* one packet on the network without payload copying, for maximum efficiency.
*
* So for example you need this kind of code to use libwebsocket_write with a
* 128-byte payload
*
* char buf[LWS_SEND_BUFFER_PRE_PADDING + 128 + LWS_SEND_BUFFER_POST_PADDING];
*
* // fill your part of the buffer... for example here it's all zeros
* memset(&buf[LWS_SEND_BUFFER_PRE_PADDING], 0, 128);
*
* libwebsocket_write(wsi, &buf[LWS_SEND_BUFFER_PRE_PADDING], 128,
* LWS_WRITE_TEXT);
*
* When sending LWS_WRITE_HTTP, there is no protocol addition and you can just
* use the whole buffer without taking care of the above.
*/
/*
* this is the frame nonce plus two header plus 8 length
* there's an additional two for mux extension per mux nesting level
* 2 byte prepend on close will already fit because control frames cannot use
* the big length style
*/
#define LWS_SEND_BUFFER_PRE_PADDING (4 + 10 + (2 * MAX_MUX_RECURSION))
#define LWS_SEND_BUFFER_POST_PADDING 4
LWS_VISIBLE LWS_EXTERN int
libwebsocket_write(struct libwebsocket *wsi, unsigned char *buf, size_t len,
enum libwebsocket_write_protocol protocol);
LWS_VISIBLE LWS_EXTERN int
libwebsockets_serve_http_file(struct libwebsocket_context *context,
struct libwebsocket *wsi, const char *file,
const char *content_type);
LWS_VISIBLE LWS_EXTERN int
libwebsockets_serve_http_file_fragment(struct libwebsocket_context *context,
struct libwebsocket *wsi);
LWS_VISIBLE LWS_EXTERN const struct libwebsocket_protocols *
libwebsockets_get_protocol(struct libwebsocket *wsi);
LWS_VISIBLE LWS_EXTERN int
libwebsocket_callback_on_writable(struct libwebsocket_context *context,
struct libwebsocket *wsi);
LWS_VISIBLE LWS_EXTERN int
libwebsocket_callback_on_writable_all_protocol(
const struct libwebsocket_protocols *protocol);
LWS_VISIBLE LWS_EXTERN int
libwebsocket_get_socket_fd(struct libwebsocket *wsi);
LWS_VISIBLE LWS_EXTERN int
libwebsocket_is_final_fragment(struct libwebsocket *wsi);
LWS_VISIBLE LWS_EXTERN unsigned char
libwebsocket_get_reserved_bits(struct libwebsocket *wsi);
LWS_VISIBLE LWS_EXTERN int
libwebsocket_rx_flow_control(struct libwebsocket *wsi, int enable);
LWS_VISIBLE LWS_EXTERN void
libwebsocket_rx_flow_allow_all_protocol(
const struct libwebsocket_protocols *protocol);
LWS_VISIBLE LWS_EXTERN size_t
libwebsockets_remaining_packet_payload(struct libwebsocket *wsi);
LWS_VISIBLE LWS_EXTERN struct libwebsocket *
libwebsocket_client_connect(struct libwebsocket_context *clients,
const char *address,
int port,
int ssl_connection,
const char *path,
const char *host,
const char *origin,
const char *protocol,
int ietf_version_or_minus_one);
LWS_VISIBLE LWS_EXTERN struct libwebsocket *
libwebsocket_client_connect_extended(struct libwebsocket_context *clients,
const char *address,
int port,
int ssl_connection,
const char *path,
const char *host,
const char *origin,
const char *protocol,
int ietf_version_or_minus_one,
void *userdata);
LWS_VISIBLE LWS_EXTERN const char *
libwebsocket_canonical_hostname(struct libwebsocket_context *context);
LWS_VISIBLE LWS_EXTERN void
libwebsockets_get_peer_addresses(struct libwebsocket_context *context,
struct libwebsocket *wsi, int fd, char *name, int name_len,
char *rip, int rip_len);
LWS_VISIBLE LWS_EXTERN int
libwebsockets_get_random(struct libwebsocket_context *context,
void *buf, int len);
LWS_VISIBLE LWS_EXTERN int
lws_daemonize(const char *_lock_path);
LWS_VISIBLE LWS_EXTERN int
lws_send_pipe_choked(struct libwebsocket *wsi);
LWS_VISIBLE LWS_EXTERN int
lws_frame_is_binary(struct libwebsocket *wsi);
LWS_VISIBLE LWS_EXTERN unsigned char *
libwebsockets_SHA1(const unsigned char *d, size_t n, unsigned char *md);
LWS_VISIBLE LWS_EXTERN int
lws_b64_encode_string(const char *in, int in_len, char *out, int out_size);
LWS_VISIBLE LWS_EXTERN int
lws_b64_decode_string(const char *in, char *out, int out_size);
LWS_VISIBLE LWS_EXTERN const char *
lws_get_library_version(void);
/* access to headers... only valid while headers valid */
LWS_VISIBLE LWS_EXTERN int
lws_hdr_total_length(struct libwebsocket *wsi, enum lws_token_indexes h);
LWS_VISIBLE LWS_EXTERN int
lws_hdr_copy(struct libwebsocket *wsi, char *dest, int len,
enum lws_token_indexes h);
/*
* Note: this is not normally needed as a user api. It's provided in case it is
* useful when integrating with other app poll loop service code.
*/
LWS_VISIBLE LWS_EXTERN int
libwebsocket_read(struct libwebsocket_context *context,
struct libwebsocket *wsi,
unsigned char *buf, size_t len);
#ifndef LWS_NO_EXTENSIONS
LWS_VISIBLE LWS_EXTERN struct libwebsocket_extension *libwebsocket_get_internal_extensions();
#endif
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,993 @@
/*
* libwebsockets - small server side websockets and web server implementation
*
* Copyright (C) 2010-2013 Andy Green <andy@warmcat.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation:
* version 2.1 of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
#ifndef __LIBWEBSOCKET_H__
#define __LIBWEBSOCKET_H__
#ifdef __cplusplus
extern "C" {
#include <cstddef>
#endif
#ifdef WIN32
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stddef.h>
#include "../win32port/win32helpers/websock-w32.h"
#include "../win32port/win32helpers/gettimeofday.h"
#define strcasecmp stricmp
#define getdtablesize() 30000
typedef int ssize_t;
#define LWS_VISIBLE
#ifdef LWS_DLL
#ifdef LWS_INTERNAL
#define LWS_EXTERN extern __declspec(dllexport)
#else
#define LWS_EXTERN extern __declspec(dllimport)
#endif
#else
#define LWS_EXTERN
#endif
#else // NOT WIN32
#include <poll.h>
#include <unistd.h>
#if defined(__GNUC__)
#define LWS_VISIBLE __attribute__((visibility("default")))
#else
#define LWS_VISIBLE
#endif
#endif
#include <assert.h>
#ifndef LWS_EXTERN
#define LWS_EXTERN extern
#endif
#define CONTEXT_PORT_NO_LISTEN 0
#define MAX_MUX_RECURSION 2
enum lws_log_levels {
LLL_ERR = 1 << 0,
LLL_WARN = 1 << 1,
LLL_NOTICE = 1 << 2,
LLL_INFO = 1 << 3,
LLL_DEBUG = 1 << 4,
LLL_PARSER = 1 << 5,
LLL_HEADER = 1 << 6,
LLL_EXT = 1 << 7,
LLL_CLIENT = 1 << 8,
LLL_LATENCY = 1 << 9,
LLL_COUNT = 10 /* set to count of valid flags */
};
LWS_VISIBLE LWS_EXTERN void _lws_log(int filter, const char *format, ...);
/* notice, warn and log are always compiled in */
#define lwsl_notice(...) _lws_log(LLL_NOTICE, __VA_ARGS__)
#define lwsl_warn(...) _lws_log(LLL_WARN, __VA_ARGS__)
#define lwsl_err(...) _lws_log(LLL_ERR, __VA_ARGS__)
/*
* weaker logging can be deselected at configure time using --disable-debug
* that gets rid of the overhead of checking while keeping _warn and _err
* active
*/
#ifdef _DEBUG
#define lwsl_info(...) _lws_log(LLL_INFO, __VA_ARGS__)
#define lwsl_debug(...) _lws_log(LLL_DEBUG, __VA_ARGS__)
#define lwsl_parser(...) _lws_log(LLL_PARSER, __VA_ARGS__)
#define lwsl_header(...) _lws_log(LLL_HEADER, __VA_ARGS__)
#define lwsl_ext(...) _lws_log(LLL_EXT, __VA_ARGS__)
#define lwsl_client(...) _lws_log(LLL_CLIENT, __VA_ARGS__)
#define lwsl_latency(...) _lws_log(LLL_LATENCY, __VA_ARGS__)
LWS_VISIBLE LWS_EXTERN void lwsl_hexdump(void *buf, size_t len);
#else /* no debug */
#define lwsl_info(...)
#define lwsl_debug(...)
#define lwsl_parser(...)
#define lwsl_header(...)
#define lwsl_ext(...)
#define lwsl_client(...)
#define lwsl_latency(...)
#define lwsl_hexdump(a, b)
#endif
enum libwebsocket_context_options {
LWS_SERVER_OPTION_REQUIRE_VALID_OPENSSL_CLIENT_CERT = 2,
LWS_SERVER_OPTION_SKIP_SERVER_CANONICAL_NAME = 4,
};
enum libwebsocket_callback_reasons {
LWS_CALLBACK_ESTABLISHED,
LWS_CALLBACK_CLIENT_CONNECTION_ERROR,
LWS_CALLBACK_CLIENT_FILTER_PRE_ESTABLISH,
LWS_CALLBACK_CLIENT_ESTABLISHED,
LWS_CALLBACK_CLOSED,
LWS_CALLBACK_RECEIVE,
LWS_CALLBACK_CLIENT_RECEIVE,
LWS_CALLBACK_CLIENT_RECEIVE_PONG,
LWS_CALLBACK_CLIENT_WRITEABLE,
LWS_CALLBACK_SERVER_WRITEABLE,
LWS_CALLBACK_HTTP,
LWS_CALLBACK_HTTP_FILE_COMPLETION,
LWS_CALLBACK_HTTP_WRITEABLE,
LWS_CALLBACK_FILTER_NETWORK_CONNECTION,
LWS_CALLBACK_FILTER_PROTOCOL_CONNECTION,
LWS_CALLBACK_OPENSSL_LOAD_EXTRA_CLIENT_VERIFY_CERTS,
LWS_CALLBACK_OPENSSL_LOAD_EXTRA_SERVER_VERIFY_CERTS,
LWS_CALLBACK_OPENSSL_PERFORM_CLIENT_CERT_VERIFICATION,
LWS_CALLBACK_CLIENT_APPEND_HANDSHAKE_HEADER,
LWS_CALLBACK_CONFIRM_EXTENSION_OKAY,
LWS_CALLBACK_CLIENT_CONFIRM_EXTENSION_SUPPORTED,
LWS_CALLBACK_PROTOCOL_INIT,
LWS_CALLBACK_PROTOCOL_DESTROY,
/* external poll() management support */
LWS_CALLBACK_ADD_POLL_FD,
LWS_CALLBACK_DEL_POLL_FD,
LWS_CALLBACK_SET_MODE_POLL_FD,
LWS_CALLBACK_CLEAR_MODE_POLL_FD,
};
#ifndef LWS_NO_EXTENSIONS
enum libwebsocket_extension_callback_reasons {
LWS_EXT_CALLBACK_SERVER_CONTEXT_CONSTRUCT,
LWS_EXT_CALLBACK_CLIENT_CONTEXT_CONSTRUCT,
LWS_EXT_CALLBACK_SERVER_CONTEXT_DESTRUCT,
LWS_EXT_CALLBACK_CLIENT_CONTEXT_DESTRUCT,
LWS_EXT_CALLBACK_CONSTRUCT,
LWS_EXT_CALLBACK_CLIENT_CONSTRUCT,
LWS_EXT_CALLBACK_CHECK_OK_TO_REALLY_CLOSE,
LWS_EXT_CALLBACK_CHECK_OK_TO_PROPOSE_EXTENSION,
LWS_EXT_CALLBACK_DESTROY,
LWS_EXT_CALLBACK_DESTROY_ANY_WSI_CLOSING,
LWS_EXT_CALLBACK_ANY_WSI_ESTABLISHED,
LWS_EXT_CALLBACK_PACKET_RX_PREPARSE,
LWS_EXT_CALLBACK_PACKET_TX_PRESEND,
LWS_EXT_CALLBACK_PACKET_TX_DO_SEND,
LWS_EXT_CALLBACK_HANDSHAKE_REPLY_TX,
LWS_EXT_CALLBACK_FLUSH_PENDING_TX,
LWS_EXT_CALLBACK_EXTENDED_PAYLOAD_RX,
LWS_EXT_CALLBACK_CAN_PROXY_CLIENT_CONNECTION,
LWS_EXT_CALLBACK_1HZ,
LWS_EXT_CALLBACK_REQUEST_ON_WRITEABLE,
LWS_EXT_CALLBACK_IS_WRITEABLE,
LWS_EXT_CALLBACK_PAYLOAD_TX,
LWS_EXT_CALLBACK_PAYLOAD_RX,
};
#endif
enum libwebsocket_write_protocol {
LWS_WRITE_TEXT,
LWS_WRITE_BINARY,
LWS_WRITE_CONTINUATION,
LWS_WRITE_HTTP,
/* special 04+ opcodes */
LWS_WRITE_CLOSE,
LWS_WRITE_PING,
LWS_WRITE_PONG,
/* flags */
LWS_WRITE_NO_FIN = 0x40,
/*
* client packet payload goes out on wire unmunged
* only useful for security tests since normal servers cannot
* decode the content if used
*/
LWS_WRITE_CLIENT_IGNORE_XOR_MASK = 0x80
};
/*
* you need these to look at headers that have been parsed if using the
* LWS_CALLBACK_FILTER_CONNECTION callback. If a header from the enum
* list below is absent, .token = NULL and token_len = 0. Otherwise .token
* points to .token_len chars containing that header content.
*/
struct lws_tokens {
char *token;
int token_len;
};
enum lws_token_indexes {
WSI_TOKEN_GET_URI,
WSI_TOKEN_HOST,
WSI_TOKEN_CONNECTION,
WSI_TOKEN_KEY1,
WSI_TOKEN_KEY2,
WSI_TOKEN_PROTOCOL,
WSI_TOKEN_UPGRADE,
WSI_TOKEN_ORIGIN,
WSI_TOKEN_DRAFT,
WSI_TOKEN_CHALLENGE,
/* new for 04 */
WSI_TOKEN_KEY,
WSI_TOKEN_VERSION,
WSI_TOKEN_SWORIGIN,
/* new for 05 */
WSI_TOKEN_EXTENSIONS,
/* client receives these */
WSI_TOKEN_ACCEPT,
WSI_TOKEN_NONCE,
WSI_TOKEN_HTTP,
WSI_TOKEN_MUXURL,
/* use token storage to stash these */
_WSI_TOKEN_CLIENT_SENT_PROTOCOLS,
_WSI_TOKEN_CLIENT_PEER_ADDRESS,
_WSI_TOKEN_CLIENT_URI,
_WSI_TOKEN_CLIENT_HOST,
_WSI_TOKEN_CLIENT_ORIGIN,
/* always last real token index*/
WSI_TOKEN_COUNT,
/* parser state additions */
WSI_TOKEN_NAME_PART,
WSI_TOKEN_SKIPPING,
WSI_TOKEN_SKIPPING_SAW_CR,
WSI_PARSING_COMPLETE,
WSI_INIT_TOKEN_MUXURL,
};
/*
* From RFC 6455
1000
1000 indicates a normal closure, meaning that the purpose for
which the connection was established has been fulfilled.
1001
1001 indicates that an endpoint is "going away", such as a server
going down or a browser having navigated away from a page.
1002
1002 indicates that an endpoint is terminating the connection due
to a protocol error.
1003
1003 indicates that an endpoint is terminating the connection
because it has received a type of data it cannot accept (e.g., an
endpoint that understands only text data MAY send this if it
receives a binary message).
1004
Reserved. The specific meaning might be defined in the future.
1005
1005 is a reserved value and MUST NOT be set as a status code in a
Close control frame by an endpoint. It is designated for use in
applications expecting a status code to indicate that no status
code was actually present.
1006
1006 is a reserved value and MUST NOT be set as a status code in a
Close control frame by an endpoint. It is designated for use in
applications expecting a status code to indicate that the
connection was closed abnormally, e.g., without sending or
receiving a Close control frame.
1007
1007 indicates that an endpoint is terminating the connection
because it has received data within a message that was not
consistent with the type of the message (e.g., non-UTF-8 [RFC3629]
data within a text message).
1008
1008 indicates that an endpoint is terminating the connection
because it has received a message that violates its policy. This
is a generic status code that can be returned when there is no
other more suitable status code (e.g., 1003 or 1009) or if there
is a need to hide specific details about the policy.
1009
1009 indicates that an endpoint is terminating the connection
because it has received a message that is too big for it to
process.
1010
1010 indicates that an endpoint (client) is terminating the
connection because it has expected the server to negotiate one or
more extension, but the server didn't return them in the response
message of the WebSocket handshake. The list of extensions that
are needed SHOULD appear in the /reason/ part of the Close frame.
Note that this status code is not used by the server, because it
can fail the WebSocket handshake instead.
1011
1011 indicates that a server is terminating the connection because
it encountered an unexpected condition that prevented it from
fulfilling the request.
1015
1015 is a reserved value and MUST NOT be set as a status code in a
Close control frame by an endpoint. It is designated for use in
applications expecting a status code to indicate that the
connection was closed due to a failure to perform a TLS handshake
(e.g., the server certificate can't be verified).
*/
enum lws_close_status {
LWS_CLOSE_STATUS_NOSTATUS = 0,
LWS_CLOSE_STATUS_NORMAL = 1000,
LWS_CLOSE_STATUS_GOINGAWAY = 1001,
LWS_CLOSE_STATUS_PROTOCOL_ERR = 1002,
LWS_CLOSE_STATUS_UNACCEPTABLE_OPCODE = 1003,
LWS_CLOSE_STATUS_RESERVED = 1004,
LWS_CLOSE_STATUS_NO_STATUS = 1005,
LWS_CLOSE_STATUS_ABNORMAL_CLOSE = 1006,
LWS_CLOSE_STATUS_INVALID_PAYLOAD = 1007,
LWS_CLOSE_STATUS_POLICY_VIOLATION = 1008,
LWS_CLOSE_STATUS_MESSAGE_TOO_LARGE = 1009,
LWS_CLOSE_STATUS_EXTENSION_REQUIRED = 1010,
LWS_CLOSE_STATUS_UNEXPECTED_CONDITION = 1011,
LWS_CLOSE_STATUS_TLS_FAILURE = 1015,
};
struct libwebsocket;
struct libwebsocket_context;
/* needed even with extensions disabled for create context */
struct libwebsocket_extension;
/**
* callback_function() - User server actions
* @context: Websockets context
* @wsi: Opaque websocket instance pointer
* @reason: The reason for the call
* @user: Pointer to per-session user data allocated by library
* @in: Pointer used for some callback reasons
* @len: Length set for some callback reasons
*
* This callback is the way the user controls what is served. All the
* protocol detail is hidden and handled by the library.
*
* For each connection / session there is user data allocated that is
* pointed to by "user". You set the size of this user data area when
* the library is initialized with libwebsocket_create_server.
*
* You get an opportunity to initialize user data when called back with
* LWS_CALLBACK_ESTABLISHED reason.
*
* LWS_CALLBACK_ESTABLISHED: after the server completes a handshake with
* an incoming client
*
* LWS_CALLBACK_CLIENT_CONNECTION_ERROR: the request client connection has
* been unable to complete a handshake with the remote server
*
* LWS_CALLBACK_CLIENT_FILTER_PRE_ESTABLISH: this is the last chance for the
* client user code to examine the http headers
* and decide to reject the connection. If the
* content in the headers is interesting to the
* client (url, etc) it needs to copy it out at
* this point since it will be destroyed before
* the CLIENT_ESTABLISHED call
*
* LWS_CALLBACK_CLIENT_ESTABLISHED: after your client connection completed
* a handshake with the remote server
*
* LWS_CALLBACK_CLOSED: when the websocket session ends
*
* LWS_CALLBACK_RECEIVE: data has appeared for this server endpoint from a
* remote client, it can be found at *in and is
* len bytes long
*
* LWS_CALLBACK_CLIENT_RECEIVE_PONG: if you elected to see PONG packets,
* they appear with this callback reason. PONG
* packets only exist in 04+ protocol
*
* LWS_CALLBACK_CLIENT_RECEIVE: data has appeared from the server for the
* client connection, it can be found at *in and
* is len bytes long
*
* LWS_CALLBACK_HTTP: an http request has come from a client that is not
* asking to upgrade the connection to a websocket
* one. This is a chance to serve http content,
* for example, to send a script to the client
* which will then open the websockets connection.
* @in points to the URI path requested and
* libwebsockets_serve_http_file() makes it very
* simple to send back a file to the client.
* Normally after sending the file you are done
* with the http connection, since the rest of the
* activity will come by websockets from the script
* that was delivered by http, so you will want to
* return 1; to close and free up the connection.
* That's important because it uses a slot in the
* total number of client connections allowed set
* by MAX_CLIENTS.
*
* LWS_CALLBACK_HTTP_WRITEABLE: you can write more down the http protocol
* link now.
*
* LWS_CALLBACK_HTTP_FILE_COMPLETION: a file requested to be send down
* http link has completed.
*
* LWS_CALLBACK_CLIENT_WRITEABLE:
* LWS_CALLBACK_SERVER_WRITEABLE: If you call
* libwebsocket_callback_on_writable() on a connection, you will
* get one of these callbacks coming when the connection socket
* is able to accept another write packet without blocking.
* If it already was able to take another packet without blocking,
* you'll get this callback at the next call to the service loop
* function. Notice that CLIENTs get LWS_CALLBACK_CLIENT_WRITEABLE
* and servers get LWS_CALLBACK_SERVER_WRITEABLE.
*
* LWS_CALLBACK_FILTER_NETWORK_CONNECTION: called when a client connects to
* the server at network level; the connection is accepted but then
* passed to this callback to decide whether to hang up immediately
* or not, based on the client IP. @in contains the connection
* socket's descriptor. Return non-zero to terminate
* the connection before sending or receiving anything.
* Because this happens immediately after the network connection
* from the client, there's no websocket protocol selected yet so
* this callback is issued only to protocol 0.
*
* LWS_CALLBACK_FILTER_PROTOCOL_CONNECTION: called when the handshake has
* been received and parsed from the client, but the response is
* not sent yet. Return non-zero to disallow the connection.
* @user is a pointer to an array of struct lws_tokens, you can
* use the header enums lws_token_indexes from libwebsockets.h
* to check for and read the supported header presence and
* content before deciding to allow the handshake to proceed or
* to kill the connection.
*
* LWS_CALLBACK_OPENSSL_LOAD_EXTRA_CLIENT_VERIFY_CERTS: if configured for
* including OpenSSL support, this callback allows your user code
* to perform extra SSL_CTX_load_verify_locations() or similar
* calls to direct OpenSSL where to find certificates the client
* can use to confirm the remote server identity. @user is the
* OpenSSL SSL_CTX*
*
* LWS_CALLBACK_OPENSSL_LOAD_EXTRA_SERVER_VERIFY_CERTS: if configured for
* including OpenSSL support, this callback allows your user code
* to load extra certifcates into the server which allow it to
* verify the validity of certificates returned by clients. @user
* is the server's OpenSSL SSL_CTX*
*
* LWS_CALLBACK_OPENSSL_PERFORM_CLIENT_CERT_VERIFICATION: if the
* libwebsockets context was created with the option
* LWS_SERVER_OPTION_REQUIRE_VALID_OPENSSL_CLIENT_CERT, then this
* callback is generated during OpenSSL verification of the cert
* sent from the client. It is sent to protocol[0] callback as
* no protocol has been negotiated on the connection yet.
* Notice that the libwebsockets context and wsi are both NULL
* during this callback. See
* http://www.openssl.org/docs/ssl/SSL_CTX_set_verify.html
* to understand more detail about the OpenSSL callback that
* generates this libwebsockets callback and the meanings of the
* arguments passed. In this callback, @user is the x509_ctx,
* @in is the ssl pointer and @len is preverify_ok
* Notice that this callback maintains libwebsocket return
* conventions, return 0 to mean the cert is OK or 1 to fail it.
* This also means that if you don't handle this callback then
* the default callback action of returning 0 allows the client
* certificates.
*
* LWS_CALLBACK_CLIENT_APPEND_HANDSHAKE_HEADER: this callback happens
* when a client handshake is being compiled. @user is NULL,
* @in is a char **, it's pointing to a char * which holds the
* next location in the header buffer where you can add
* headers, and @len is the remaining space in the header buffer,
* which is typically some hundreds of bytes. So, to add a canned
* cookie, your handler code might look similar to:
*
* char **p = (char **)in;
*
* if (len < 100)
* return 1;
*
* *p += sprintf(*p, "Cookie: a=b\x0d\x0a");
*
* return 0;
*
* Notice if you add anything, you just have to take care about
* the CRLF on the line you added. Obviously this callback is
* optional, if you don't handle it everything is fine.
*
* Notice the callback is coming to protocols[0] all the time,
* because there is no specific protocol handshook yet.
*
* LWS_CALLBACK_CONFIRM_EXTENSION_OKAY: When the server handshake code
* sees that it does support a requested extension, before
* accepting the extension by additing to the list sent back to
* the client it gives this callback just to check that it's okay
* to use that extension. It calls back to the requested protocol
* and with @in being the extension name, @len is 0 and @user is
* valid. Note though at this time the ESTABLISHED callback hasn't
* happened yet so if you initialize @user content there, @user
* content during this callback might not be useful for anything.
* Notice this callback comes to protocols[0].
*
* LWS_CALLBACK_CLIENT_CONFIRM_EXTENSION_SUPPORTED: When a client
* connection is being prepared to start a handshake to a server,
* each supported extension is checked with protocols[0] callback
* with this reason, giving the user code a chance to suppress the
* claim to support that extension by returning non-zero. If
* unhandled, by default 0 will be returned and the extension
* support included in the header to the server. Notice this
* callback comes to protocols[0].
*
* LWS_CALLBACK_PROTOCOL_INIT: One-time call per protocol so it can
* do initial setup / allocations etc
*
* LWS_CALLBACK_PROTOCOL_DESTROY: One-time call per protocol indicating
* this protocol won't get used at all after this callback, the
* context is getting destroyed. Take the opportunity to
* deallocate everything that was allocated by the protocol.
*
* The next four reasons are optional and only need taking care of if you
* will be integrating libwebsockets sockets into an external polling
* array.
*
* LWS_CALLBACK_ADD_POLL_FD: libwebsocket deals with its poll() loop
* internally, but in the case you are integrating with another
* server you will need to have libwebsocket sockets share a
* polling array with the other server. This and the other
* POLL_FD related callbacks let you put your specialized
* poll array interface code in the callback for protocol 0, the
* first protocol you support, usually the HTTP protocol in the
* serving case. This callback happens when a socket needs to be
* added to the polling loop: @in contains the fd, and
* @len is the events bitmap (like, POLLIN). If you are using the
* internal polling loop (the "service" callback), you can just
* ignore these callbacks.
*
* LWS_CALLBACK_DEL_POLL_FD: This callback happens when a socket descriptor
* needs to be removed from an external polling array. @in is
* the socket desricptor. If you are using the internal polling
* loop, you can just ignore it.
*
* LWS_CALLBACK_SET_MODE_POLL_FD: This callback happens when libwebsockets
* wants to modify the events for the socket descriptor in @in.
* The handler should OR @len on to the events member of the pollfd
* struct for this socket descriptor. If you are using the
* internal polling loop, you can just ignore it.
*
* LWS_CALLBACK_CLEAR_MODE_POLL_FD: This callback occurs when libwebsockets
* wants to modify the events for the socket descriptor in @in.
* The handler should AND ~@len on to the events member of the
* pollfd struct for this socket descriptor. If you are using the
* internal polling loop, you can just ignore it.
*/
LWS_VISIBLE LWS_EXTERN int callback(struct libwebsocket_context *context,
struct libwebsocket *wsi,
enum libwebsocket_callback_reasons reason, void *user,
void *in, size_t len);
typedef int (callback_function)(struct libwebsocket_context *context,
struct libwebsocket *wsi,
enum libwebsocket_callback_reasons reason, void *user,
void *in, size_t len);
#ifndef LWS_NO_EXTENSIONS
/**
* extension_callback_function() - Hooks to allow extensions to operate
* @context: Websockets context
* @ext: This extension
* @wsi: Opaque websocket instance pointer
* @reason: The reason for the call
* @user: Pointer to per-session user data allocated by library
* @in: Pointer used for some callback reasons
* @len: Length set for some callback reasons
*
* Each extension that is active on a particular connection receives
* callbacks during the connection lifetime to allow the extension to
* operate on websocket data and manage itself.
*
* Libwebsockets takes care of allocating and freeing "user" memory for
* each active extension on each connection. That is what is pointed to
* by the @user parameter.
*
* LWS_EXT_CALLBACK_CONSTRUCT: called when the server has decided to
* select this extension from the list provided by the client,
* just before the server will send back the handshake accepting
* the connection with this extension active. This gives the
* extension a chance to initialize its connection context found
* in @user.
*
* LWS_EXT_CALLBACK_CLIENT_CONSTRUCT: same as LWS_EXT_CALLBACK_CONSTRUCT
* but called when client is instantiating this extension. Some
* extensions will work the same on client and server side and then
* you can just merge handlers for both CONSTRUCTS.
*
* LWS_EXT_CALLBACK_DESTROY: called when the connection the extension was
* being used on is about to be closed and deallocated. It's the
* last chance for the extension to deallocate anything it has
* allocated in the user data (pointed to by @user) before the
* user data is deleted. This same callback is used whether you
* are in client or server instantiation context.
*
* LWS_EXT_CALLBACK_PACKET_RX_PREPARSE: when this extension was active on
* a connection, and a packet of data arrived at the connection,
* it is passed to this callback to give the extension a chance to
* change the data, eg, decompress it. @user is pointing to the
* extension's private connection context data, @in is pointing
* to an lws_tokens struct, it consists of a char * pointer called
* token, and an int called token_len. At entry, these are
* set to point to the received buffer and set to the content
* length. If the extension will grow the content, it should use
* a new buffer allocated in its private user context data and
* set the pointed-to lws_tokens members to point to its buffer.
*
* LWS_EXT_CALLBACK_PACKET_TX_PRESEND: this works the same way as
* LWS_EXT_CALLBACK_PACKET_RX_PREPARSE above, except it gives the
* extension a chance to change websocket data just before it will
* be sent out. Using the same lws_token pointer scheme in @in,
* the extension can change the buffer and the length to be
* transmitted how it likes. Again if it wants to grow the
* buffer safely, it should copy the data into its own buffer and
* set the lws_tokens token pointer to it.
*/
LWS_VISIBLE LWS_EXTERN int extension_callback(struct libwebsocket_context *context,
struct libwebsocket_extension *ext,
struct libwebsocket *wsi,
enum libwebsocket_extension_callback_reasons reason,
void *user, void *in, size_t len);
typedef int (extension_callback_function)(struct libwebsocket_context *context,
struct libwebsocket_extension *ext,
struct libwebsocket *wsi,
enum libwebsocket_extension_callback_reasons reason,
void *user, void *in, size_t len);
#endif
/**
* struct libwebsocket_protocols - List of protocols and handlers server
* supports.
* @name: Protocol name that must match the one given in the client
* Javascript new WebSocket(url, 'protocol') name
* @callback: The service callback used for this protocol. It allows the
* service action for an entire protocol to be encapsulated in
* the protocol-specific callback
* @per_session_data_size: Each new connection using this protocol gets
* this much memory allocated on connection establishment and
* freed on connection takedown. A pointer to this per-connection
* allocation is passed into the callback in the 'user' parameter
* @rx_buffer_size: if you want atomic frames delivered to the callback, you
* should set this to the size of the biggest legal frame that
* you support. If the frame size is exceeded, there is no
* error, but the buffer will spill to the user callback when
* full, which you can detect by using
* libwebsockets_remaining_packet_payload(). Notice that you
* just talk about frame size here, the LWS_SEND_BUFFER_PRE_PADDING
* and post-padding are automatically also allocated on top.
* @owning_server: the server init call fills in this opaque pointer when
* registering this protocol with the server.
* @protocol_index: which protocol we are starting from zero
*
* This structure represents one protocol supported by the server. An
* array of these structures is passed to libwebsocket_create_server()
* allows as many protocols as you like to be handled by one server.
*/
struct libwebsocket_protocols {
const char *name;
callback_function *callback;
size_t per_session_data_size;
size_t rx_buffer_size;
/*
* below are filled in on server init and can be left uninitialized,
* no need for user to use them directly either
*/
struct libwebsocket_context *owning_server;
int protocol_index;
};
#ifndef LWS_NO_EXTENSIONS
/**
* struct libwebsocket_extension - An extension we know how to cope with
*
* @name: Formal extension name, eg, "deflate-stream"
* @callback: Service callback
* @per_session_data_size: Libwebsockets will auto-malloc this much
* memory for the use of the extension, a pointer
* to it comes in the @user callback parameter
* @per_context_private_data: Optional storage for this extension that
* is per-context, so it can track stuff across
* all sessions, etc, if it wants
*/
struct libwebsocket_extension {
const char *name;
extension_callback_function *callback;
size_t per_session_data_size;
void *per_context_private_data;
};
#endif
/**
* struct lws_context_creation_info: parameters to create context with
*
* @port: Port to listen on... you can use 0 to suppress listening on
* any port, that's what you want if you are not running a
* websocket server at all but just using it as a client
* @iface: NULL to bind the listen socket to all interfaces, or the
* interface name, eg, "eth2"
* @protocols: Array of structures listing supported protocols and a protocol-
* specific callback for each one. The list is ended with an
* entry that has a NULL callback pointer.
* It's not const because we write the owning_server member
* @extensions: NULL or array of libwebsocket_extension structs listing the
* extensions this context supports. If you configured with
* --without-extensions, you should give NULL here.
* @ssl_cert_filepath: If libwebsockets was compiled to use ssl, and you want
* to listen using SSL, set to the filepath to fetch the
* server cert from, otherwise NULL for unencrypted
* @ssl_private_key_filepath: filepath to private key if wanting SSL mode,
* else ignored
* @ssl_ca_filepath: CA certificate filepath or NULL
* @ssl_cipher_list: List of valid ciphers to use (eg,
* "RC4-MD5:RC4-SHA:AES128-SHA:AES256-SHA:HIGH:!DSS:!aNULL"
* or you can leave it as NULL to get "DEFAULT"
* @gid: group id to change to after setting listen socket, or -1.
* @uid: user id to change to after setting listen socket, or -1.
* @options: 0, or LWS_SERVER_OPTION_DEFEAT_CLIENT_MASK
* @user: optional user pointer that can be recovered via the context
* pointer using libwebsocket_context_user
* @ka_time: 0 for no keepalive, otherwise apply this keepalive timeout to
* all libwebsocket sockets, client or server
* @ka_probes: if ka_time was nonzero, after the timeout expires how many
* times to try to get a response from the peer before giving up
* and killing the connection
* @ka_interval: if ka_time was nonzero, how long to wait before each ka_probes
* attempt
*/
struct lws_context_creation_info {
int port;
const char *iface;
struct libwebsocket_protocols *protocols;
struct libwebsocket_extension *extensions;
const char *ssl_cert_filepath;
const char *ssl_private_key_filepath;
const char *ssl_ca_filepath;
const char *ssl_cipher_list;
int gid;
int uid;
unsigned int options;
void *user;
int ka_time;
int ka_probes;
int ka_interval;
};
LWS_VISIBLE LWS_EXTERN
void lws_set_log_level(int level,
void (*log_emit_function)(int level, const char *line));
LWS_VISIBLE LWS_EXTERN void
lwsl_emit_syslog(int level, const char *line);
LWS_VISIBLE LWS_EXTERN struct libwebsocket_context *
libwebsocket_create_context(struct lws_context_creation_info *info);
LWS_VISIBLE LWS_EXTERN void
libwebsocket_context_destroy(struct libwebsocket_context *context);
LWS_VISIBLE LWS_EXTERN int
libwebsocket_service(struct libwebsocket_context *context, int timeout_ms);
LWS_VISIBLE LWS_EXTERN int
libwebsocket_service_fd(struct libwebsocket_context *context,
struct pollfd *pollfd);
LWS_VISIBLE LWS_EXTERN void *
libwebsocket_context_user(struct libwebsocket_context *context);
/*
* IMPORTANT NOTICE!
*
* When sending with websocket protocol (LWS_WRITE_TEXT or LWS_WRITE_BINARY)
* the send buffer has to have LWS_SEND_BUFFER_PRE_PADDING bytes valid BEFORE
* buf, and LWS_SEND_BUFFER_POST_PADDING bytes valid AFTER (buf + len).
*
* This allows us to add protocol info before and after the data, and send as
* one packet on the network without payload copying, for maximum efficiency.
*
* So for example you need this kind of code to use libwebsocket_write with a
* 128-byte payload
*
* char buf[LWS_SEND_BUFFER_PRE_PADDING + 128 + LWS_SEND_BUFFER_POST_PADDING];
*
* // fill your part of the buffer... for example here it's all zeros
* memset(&buf[LWS_SEND_BUFFER_PRE_PADDING], 0, 128);
*
* libwebsocket_write(wsi, &buf[LWS_SEND_BUFFER_PRE_PADDING], 128,
* LWS_WRITE_TEXT);
*
* When sending LWS_WRITE_HTTP, there is no protocol addition and you can just
* use the whole buffer without taking care of the above.
*/
/*
* this is the frame nonce plus two header plus 8 length
* there's an additional two for mux extension per mux nesting level
* 2 byte prepend on close will already fit because control frames cannot use
* the big length style
*/
#define LWS_SEND_BUFFER_PRE_PADDING (4 + 10 + (2 * MAX_MUX_RECURSION))
#define LWS_SEND_BUFFER_POST_PADDING 4
LWS_VISIBLE LWS_EXTERN int
libwebsocket_write(struct libwebsocket *wsi, unsigned char *buf, size_t len,
enum libwebsocket_write_protocol protocol);
LWS_VISIBLE LWS_EXTERN int
libwebsockets_serve_http_file(struct libwebsocket_context *context,
struct libwebsocket *wsi, const char *file,
const char *content_type);
LWS_VISIBLE LWS_EXTERN int
libwebsockets_serve_http_file_fragment(struct libwebsocket_context *context,
struct libwebsocket *wsi);
LWS_VISIBLE LWS_EXTERN const struct libwebsocket_protocols *
libwebsockets_get_protocol(struct libwebsocket *wsi);
LWS_VISIBLE LWS_EXTERN int
libwebsocket_callback_on_writable(struct libwebsocket_context *context,
struct libwebsocket *wsi);
LWS_VISIBLE LWS_EXTERN int
libwebsocket_callback_on_writable_all_protocol(
const struct libwebsocket_protocols *protocol);
LWS_VISIBLE LWS_EXTERN int
libwebsocket_get_socket_fd(struct libwebsocket *wsi);
LWS_VISIBLE LWS_EXTERN int
libwebsocket_is_final_fragment(struct libwebsocket *wsi);
LWS_VISIBLE LWS_EXTERN unsigned char
libwebsocket_get_reserved_bits(struct libwebsocket *wsi);
LWS_VISIBLE LWS_EXTERN int
libwebsocket_rx_flow_control(struct libwebsocket *wsi, int enable);
LWS_VISIBLE LWS_EXTERN void
libwebsocket_rx_flow_allow_all_protocol(
const struct libwebsocket_protocols *protocol);
LWS_VISIBLE LWS_EXTERN size_t
libwebsockets_remaining_packet_payload(struct libwebsocket *wsi);
LWS_VISIBLE LWS_EXTERN struct libwebsocket *
libwebsocket_client_connect(struct libwebsocket_context *clients,
const char *address,
int port,
int ssl_connection,
const char *path,
const char *host,
const char *origin,
const char *protocol,
int ietf_version_or_minus_one);
LWS_VISIBLE LWS_EXTERN struct libwebsocket *
libwebsocket_client_connect_extended(struct libwebsocket_context *clients,
const char *address,
int port,
int ssl_connection,
const char *path,
const char *host,
const char *origin,
const char *protocol,
int ietf_version_or_minus_one,
void *userdata);
LWS_VISIBLE LWS_EXTERN const char *
libwebsocket_canonical_hostname(struct libwebsocket_context *context);
LWS_VISIBLE LWS_EXTERN void
libwebsockets_get_peer_addresses(struct libwebsocket_context *context,
struct libwebsocket *wsi, int fd, char *name, int name_len,
char *rip, int rip_len);
LWS_VISIBLE LWS_EXTERN int
libwebsockets_get_random(struct libwebsocket_context *context,
void *buf, int len);
LWS_VISIBLE LWS_EXTERN int
lws_daemonize(const char *_lock_path);
LWS_VISIBLE LWS_EXTERN int
lws_send_pipe_choked(struct libwebsocket *wsi);
LWS_VISIBLE LWS_EXTERN int
lws_frame_is_binary(struct libwebsocket *wsi);
LWS_VISIBLE LWS_EXTERN unsigned char *
libwebsockets_SHA1(const unsigned char *d, size_t n, unsigned char *md);
LWS_VISIBLE LWS_EXTERN int
lws_b64_encode_string(const char *in, int in_len, char *out, int out_size);
LWS_VISIBLE LWS_EXTERN int
lws_b64_decode_string(const char *in, char *out, int out_size);
LWS_VISIBLE LWS_EXTERN const char *
lws_get_library_version(void);
/* access to headers... only valid while headers valid */
LWS_VISIBLE LWS_EXTERN int
lws_hdr_total_length(struct libwebsocket *wsi, enum lws_token_indexes h);
LWS_VISIBLE LWS_EXTERN int
lws_hdr_copy(struct libwebsocket *wsi, char *dest, int len,
enum lws_token_indexes h);
/*
* Note: this is not normally needed as a user api. It's provided in case it is
* useful when integrating with other app poll loop service code.
*/
LWS_VISIBLE LWS_EXTERN int
libwebsocket_read(struct libwebsocket_context *context,
struct libwebsocket *wsi,
unsigned char *buf, size_t len);
#ifndef LWS_NO_EXTENSIONS
LWS_VISIBLE LWS_EXTERN struct libwebsocket_extension *libwebsocket_get_internal_extensions();
#endif
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1 @@
ee4ee6cc26274f6d3138d08d429d6ba49b629f53

View File

@ -0,0 +1,993 @@
/*
* libwebsockets - small server side websockets and web server implementation
*
* Copyright (C) 2010-2013 Andy Green <andy@warmcat.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation:
* version 2.1 of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
#ifndef __LIBWEBSOCKET_H__
#define __LIBWEBSOCKET_H__
#ifdef __cplusplus
extern "C" {
#include <cstddef>
#endif
#ifdef WIN32
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stddef.h>
#include "win32helpers/websock-w32.h"
//#include "win32helpers/gettimeofday.h"
#define strcasecmp stricmp
#define getdtablesize() 30000
typedef int ssize_t;
#define LWS_VISIBLE
#ifdef LWS_DLL
#ifdef LWS_INTERNAL
#define LWS_EXTERN extern __declspec(dllexport)
#else
#define LWS_EXTERN extern __declspec(dllimport)
#endif
#else
#define LWS_EXTERN
#endif
#else // NOT WIN32
#include <poll.h>
#include <unistd.h>
#if defined(__GNUC__)
#define LWS_VISIBLE __attribute__((visibility("default")))
#else
#define LWS_VISIBLE
#endif
#endif
#include <assert.h>
#ifndef LWS_EXTERN
#define LWS_EXTERN extern
#endif
#define CONTEXT_PORT_NO_LISTEN 0
#define MAX_MUX_RECURSION 2
enum lws_log_levels {
LLL_ERR = 1 << 0,
LLL_WARN = 1 << 1,
LLL_NOTICE = 1 << 2,
LLL_INFO = 1 << 3,
LLL_DEBUG = 1 << 4,
LLL_PARSER = 1 << 5,
LLL_HEADER = 1 << 6,
LLL_EXT = 1 << 7,
LLL_CLIENT = 1 << 8,
LLL_LATENCY = 1 << 9,
LLL_COUNT = 10 /* set to count of valid flags */
};
LWS_VISIBLE LWS_EXTERN void _lws_log(int filter, const char *format, ...);
/* notice, warn and log are always compiled in */
#define lwsl_notice(...) _lws_log(LLL_NOTICE, __VA_ARGS__)
#define lwsl_warn(...) _lws_log(LLL_WARN, __VA_ARGS__)
#define lwsl_err(...) _lws_log(LLL_ERR, __VA_ARGS__)
/*
* weaker logging can be deselected at configure time using --disable-debug
* that gets rid of the overhead of checking while keeping _warn and _err
* active
*/
#ifdef _DEBUG
#define lwsl_info(...) _lws_log(LLL_INFO, __VA_ARGS__)
#define lwsl_debug(...) _lws_log(LLL_DEBUG, __VA_ARGS__)
#define lwsl_parser(...) _lws_log(LLL_PARSER, __VA_ARGS__)
#define lwsl_header(...) _lws_log(LLL_HEADER, __VA_ARGS__)
#define lwsl_ext(...) _lws_log(LLL_EXT, __VA_ARGS__)
#define lwsl_client(...) _lws_log(LLL_CLIENT, __VA_ARGS__)
#define lwsl_latency(...) _lws_log(LLL_LATENCY, __VA_ARGS__)
LWS_VISIBLE LWS_EXTERN void lwsl_hexdump(void *buf, size_t len);
#else /* no debug */
#define lwsl_info(...)
#define lwsl_debug(...)
#define lwsl_parser(...)
#define lwsl_header(...)
#define lwsl_ext(...)
#define lwsl_client(...)
#define lwsl_latency(...)
#define lwsl_hexdump(a, b)
#endif
enum libwebsocket_context_options {
LWS_SERVER_OPTION_REQUIRE_VALID_OPENSSL_CLIENT_CERT = 2,
LWS_SERVER_OPTION_SKIP_SERVER_CANONICAL_NAME = 4,
};
enum libwebsocket_callback_reasons {
LWS_CALLBACK_ESTABLISHED,
LWS_CALLBACK_CLIENT_CONNECTION_ERROR,
LWS_CALLBACK_CLIENT_FILTER_PRE_ESTABLISH,
LWS_CALLBACK_CLIENT_ESTABLISHED,
LWS_CALLBACK_CLOSED,
LWS_CALLBACK_RECEIVE,
LWS_CALLBACK_CLIENT_RECEIVE,
LWS_CALLBACK_CLIENT_RECEIVE_PONG,
LWS_CALLBACK_CLIENT_WRITEABLE,
LWS_CALLBACK_SERVER_WRITEABLE,
LWS_CALLBACK_HTTP,
LWS_CALLBACK_HTTP_FILE_COMPLETION,
LWS_CALLBACK_HTTP_WRITEABLE,
LWS_CALLBACK_FILTER_NETWORK_CONNECTION,
LWS_CALLBACK_FILTER_PROTOCOL_CONNECTION,
LWS_CALLBACK_OPENSSL_LOAD_EXTRA_CLIENT_VERIFY_CERTS,
LWS_CALLBACK_OPENSSL_LOAD_EXTRA_SERVER_VERIFY_CERTS,
LWS_CALLBACK_OPENSSL_PERFORM_CLIENT_CERT_VERIFICATION,
LWS_CALLBACK_CLIENT_APPEND_HANDSHAKE_HEADER,
LWS_CALLBACK_CONFIRM_EXTENSION_OKAY,
LWS_CALLBACK_CLIENT_CONFIRM_EXTENSION_SUPPORTED,
LWS_CALLBACK_PROTOCOL_INIT,
LWS_CALLBACK_PROTOCOL_DESTROY,
/* external poll() management support */
LWS_CALLBACK_ADD_POLL_FD,
LWS_CALLBACK_DEL_POLL_FD,
LWS_CALLBACK_SET_MODE_POLL_FD,
LWS_CALLBACK_CLEAR_MODE_POLL_FD,
};
#ifndef LWS_NO_EXTENSIONS
enum libwebsocket_extension_callback_reasons {
LWS_EXT_CALLBACK_SERVER_CONTEXT_CONSTRUCT,
LWS_EXT_CALLBACK_CLIENT_CONTEXT_CONSTRUCT,
LWS_EXT_CALLBACK_SERVER_CONTEXT_DESTRUCT,
LWS_EXT_CALLBACK_CLIENT_CONTEXT_DESTRUCT,
LWS_EXT_CALLBACK_CONSTRUCT,
LWS_EXT_CALLBACK_CLIENT_CONSTRUCT,
LWS_EXT_CALLBACK_CHECK_OK_TO_REALLY_CLOSE,
LWS_EXT_CALLBACK_CHECK_OK_TO_PROPOSE_EXTENSION,
LWS_EXT_CALLBACK_DESTROY,
LWS_EXT_CALLBACK_DESTROY_ANY_WSI_CLOSING,
LWS_EXT_CALLBACK_ANY_WSI_ESTABLISHED,
LWS_EXT_CALLBACK_PACKET_RX_PREPARSE,
LWS_EXT_CALLBACK_PACKET_TX_PRESEND,
LWS_EXT_CALLBACK_PACKET_TX_DO_SEND,
LWS_EXT_CALLBACK_HANDSHAKE_REPLY_TX,
LWS_EXT_CALLBACK_FLUSH_PENDING_TX,
LWS_EXT_CALLBACK_EXTENDED_PAYLOAD_RX,
LWS_EXT_CALLBACK_CAN_PROXY_CLIENT_CONNECTION,
LWS_EXT_CALLBACK_1HZ,
LWS_EXT_CALLBACK_REQUEST_ON_WRITEABLE,
LWS_EXT_CALLBACK_IS_WRITEABLE,
LWS_EXT_CALLBACK_PAYLOAD_TX,
LWS_EXT_CALLBACK_PAYLOAD_RX,
};
#endif
enum libwebsocket_write_protocol {
LWS_WRITE_TEXT,
LWS_WRITE_BINARY,
LWS_WRITE_CONTINUATION,
LWS_WRITE_HTTP,
/* special 04+ opcodes */
LWS_WRITE_CLOSE,
LWS_WRITE_PING,
LWS_WRITE_PONG,
/* flags */
LWS_WRITE_NO_FIN = 0x40,
/*
* client packet payload goes out on wire unmunged
* only useful for security tests since normal servers cannot
* decode the content if used
*/
LWS_WRITE_CLIENT_IGNORE_XOR_MASK = 0x80
};
/*
* you need these to look at headers that have been parsed if using the
* LWS_CALLBACK_FILTER_CONNECTION callback. If a header from the enum
* list below is absent, .token = NULL and token_len = 0. Otherwise .token
* points to .token_len chars containing that header content.
*/
struct lws_tokens {
char *token;
int token_len;
};
enum lws_token_indexes {
WSI_TOKEN_GET_URI,
WSI_TOKEN_HOST,
WSI_TOKEN_CONNECTION,
WSI_TOKEN_KEY1,
WSI_TOKEN_KEY2,
WSI_TOKEN_PROTOCOL,
WSI_TOKEN_UPGRADE,
WSI_TOKEN_ORIGIN,
WSI_TOKEN_DRAFT,
WSI_TOKEN_CHALLENGE,
/* new for 04 */
WSI_TOKEN_KEY,
WSI_TOKEN_VERSION,
WSI_TOKEN_SWORIGIN,
/* new for 05 */
WSI_TOKEN_EXTENSIONS,
/* client receives these */
WSI_TOKEN_ACCEPT,
WSI_TOKEN_NONCE,
WSI_TOKEN_HTTP,
WSI_TOKEN_MUXURL,
/* use token storage to stash these */
_WSI_TOKEN_CLIENT_SENT_PROTOCOLS,
_WSI_TOKEN_CLIENT_PEER_ADDRESS,
_WSI_TOKEN_CLIENT_URI,
_WSI_TOKEN_CLIENT_HOST,
_WSI_TOKEN_CLIENT_ORIGIN,
/* always last real token index*/
WSI_TOKEN_COUNT,
/* parser state additions */
WSI_TOKEN_NAME_PART,
WSI_TOKEN_SKIPPING,
WSI_TOKEN_SKIPPING_SAW_CR,
WSI_PARSING_COMPLETE,
WSI_INIT_TOKEN_MUXURL,
};
/*
* From RFC 6455
1000
1000 indicates a normal closure, meaning that the purpose for
which the connection was established has been fulfilled.
1001
1001 indicates that an endpoint is "going away", such as a server
going down or a browser having navigated away from a page.
1002
1002 indicates that an endpoint is terminating the connection due
to a protocol error.
1003
1003 indicates that an endpoint is terminating the connection
because it has received a type of data it cannot accept (e.g., an
endpoint that understands only text data MAY send this if it
receives a binary message).
1004
Reserved. The specific meaning might be defined in the future.
1005
1005 is a reserved value and MUST NOT be set as a status code in a
Close control frame by an endpoint. It is designated for use in
applications expecting a status code to indicate that no status
code was actually present.
1006
1006 is a reserved value and MUST NOT be set as a status code in a
Close control frame by an endpoint. It is designated for use in
applications expecting a status code to indicate that the
connection was closed abnormally, e.g., without sending or
receiving a Close control frame.
1007
1007 indicates that an endpoint is terminating the connection
because it has received data within a message that was not
consistent with the type of the message (e.g., non-UTF-8 [RFC3629]
data within a text message).
1008
1008 indicates that an endpoint is terminating the connection
because it has received a message that violates its policy. This
is a generic status code that can be returned when there is no
other more suitable status code (e.g., 1003 or 1009) or if there
is a need to hide specific details about the policy.
1009
1009 indicates that an endpoint is terminating the connection
because it has received a message that is too big for it to
process.
1010
1010 indicates that an endpoint (client) is terminating the
connection because it has expected the server to negotiate one or
more extension, but the server didn't return them in the response
message of the WebSocket handshake. The list of extensions that
are needed SHOULD appear in the /reason/ part of the Close frame.
Note that this status code is not used by the server, because it
can fail the WebSocket handshake instead.
1011
1011 indicates that a server is terminating the connection because
it encountered an unexpected condition that prevented it from
fulfilling the request.
1015
1015 is a reserved value and MUST NOT be set as a status code in a
Close control frame by an endpoint. It is designated for use in
applications expecting a status code to indicate that the
connection was closed due to a failure to perform a TLS handshake
(e.g., the server certificate can't be verified).
*/
enum lws_close_status {
LWS_CLOSE_STATUS_NOSTATUS = 0,
LWS_CLOSE_STATUS_NORMAL = 1000,
LWS_CLOSE_STATUS_GOINGAWAY = 1001,
LWS_CLOSE_STATUS_PROTOCOL_ERR = 1002,
LWS_CLOSE_STATUS_UNACCEPTABLE_OPCODE = 1003,
LWS_CLOSE_STATUS_RESERVED = 1004,
LWS_CLOSE_STATUS_NO_STATUS = 1005,
LWS_CLOSE_STATUS_ABNORMAL_CLOSE = 1006,
LWS_CLOSE_STATUS_INVALID_PAYLOAD = 1007,
LWS_CLOSE_STATUS_POLICY_VIOLATION = 1008,
LWS_CLOSE_STATUS_MESSAGE_TOO_LARGE = 1009,
LWS_CLOSE_STATUS_EXTENSION_REQUIRED = 1010,
LWS_CLOSE_STATUS_UNEXPECTED_CONDITION = 1011,
LWS_CLOSE_STATUS_TLS_FAILURE = 1015,
};
struct libwebsocket;
struct libwebsocket_context;
/* needed even with extensions disabled for create context */
struct libwebsocket_extension;
/**
* callback_function() - User server actions
* @context: Websockets context
* @wsi: Opaque websocket instance pointer
* @reason: The reason for the call
* @user: Pointer to per-session user data allocated by library
* @in: Pointer used for some callback reasons
* @len: Length set for some callback reasons
*
* This callback is the way the user controls what is served. All the
* protocol detail is hidden and handled by the library.
*
* For each connection / session there is user data allocated that is
* pointed to by "user". You set the size of this user data area when
* the library is initialized with libwebsocket_create_server.
*
* You get an opportunity to initialize user data when called back with
* LWS_CALLBACK_ESTABLISHED reason.
*
* LWS_CALLBACK_ESTABLISHED: after the server completes a handshake with
* an incoming client
*
* LWS_CALLBACK_CLIENT_CONNECTION_ERROR: the request client connection has
* been unable to complete a handshake with the remote server
*
* LWS_CALLBACK_CLIENT_FILTER_PRE_ESTABLISH: this is the last chance for the
* client user code to examine the http headers
* and decide to reject the connection. If the
* content in the headers is interesting to the
* client (url, etc) it needs to copy it out at
* this point since it will be destroyed before
* the CLIENT_ESTABLISHED call
*
* LWS_CALLBACK_CLIENT_ESTABLISHED: after your client connection completed
* a handshake with the remote server
*
* LWS_CALLBACK_CLOSED: when the websocket session ends
*
* LWS_CALLBACK_RECEIVE: data has appeared for this server endpoint from a
* remote client, it can be found at *in and is
* len bytes long
*
* LWS_CALLBACK_CLIENT_RECEIVE_PONG: if you elected to see PONG packets,
* they appear with this callback reason. PONG
* packets only exist in 04+ protocol
*
* LWS_CALLBACK_CLIENT_RECEIVE: data has appeared from the server for the
* client connection, it can be found at *in and
* is len bytes long
*
* LWS_CALLBACK_HTTP: an http request has come from a client that is not
* asking to upgrade the connection to a websocket
* one. This is a chance to serve http content,
* for example, to send a script to the client
* which will then open the websockets connection.
* @in points to the URI path requested and
* libwebsockets_serve_http_file() makes it very
* simple to send back a file to the client.
* Normally after sending the file you are done
* with the http connection, since the rest of the
* activity will come by websockets from the script
* that was delivered by http, so you will want to
* return 1; to close and free up the connection.
* That's important because it uses a slot in the
* total number of client connections allowed set
* by MAX_CLIENTS.
*
* LWS_CALLBACK_HTTP_WRITEABLE: you can write more down the http protocol
* link now.
*
* LWS_CALLBACK_HTTP_FILE_COMPLETION: a file requested to be send down
* http link has completed.
*
* LWS_CALLBACK_CLIENT_WRITEABLE:
* LWS_CALLBACK_SERVER_WRITEABLE: If you call
* libwebsocket_callback_on_writable() on a connection, you will
* get one of these callbacks coming when the connection socket
* is able to accept another write packet without blocking.
* If it already was able to take another packet without blocking,
* you'll get this callback at the next call to the service loop
* function. Notice that CLIENTs get LWS_CALLBACK_CLIENT_WRITEABLE
* and servers get LWS_CALLBACK_SERVER_WRITEABLE.
*
* LWS_CALLBACK_FILTER_NETWORK_CONNECTION: called when a client connects to
* the server at network level; the connection is accepted but then
* passed to this callback to decide whether to hang up immediately
* or not, based on the client IP. @in contains the connection
* socket's descriptor. Return non-zero to terminate
* the connection before sending or receiving anything.
* Because this happens immediately after the network connection
* from the client, there's no websocket protocol selected yet so
* this callback is issued only to protocol 0.
*
* LWS_CALLBACK_FILTER_PROTOCOL_CONNECTION: called when the handshake has
* been received and parsed from the client, but the response is
* not sent yet. Return non-zero to disallow the connection.
* @user is a pointer to an array of struct lws_tokens, you can
* use the header enums lws_token_indexes from libwebsockets.h
* to check for and read the supported header presence and
* content before deciding to allow the handshake to proceed or
* to kill the connection.
*
* LWS_CALLBACK_OPENSSL_LOAD_EXTRA_CLIENT_VERIFY_CERTS: if configured for
* including OpenSSL support, this callback allows your user code
* to perform extra SSL_CTX_load_verify_locations() or similar
* calls to direct OpenSSL where to find certificates the client
* can use to confirm the remote server identity. @user is the
* OpenSSL SSL_CTX*
*
* LWS_CALLBACK_OPENSSL_LOAD_EXTRA_SERVER_VERIFY_CERTS: if configured for
* including OpenSSL support, this callback allows your user code
* to load extra certifcates into the server which allow it to
* verify the validity of certificates returned by clients. @user
* is the server's OpenSSL SSL_CTX*
*
* LWS_CALLBACK_OPENSSL_PERFORM_CLIENT_CERT_VERIFICATION: if the
* libwebsockets context was created with the option
* LWS_SERVER_OPTION_REQUIRE_VALID_OPENSSL_CLIENT_CERT, then this
* callback is generated during OpenSSL verification of the cert
* sent from the client. It is sent to protocol[0] callback as
* no protocol has been negotiated on the connection yet.
* Notice that the libwebsockets context and wsi are both NULL
* during this callback. See
* http://www.openssl.org/docs/ssl/SSL_CTX_set_verify.html
* to understand more detail about the OpenSSL callback that
* generates this libwebsockets callback and the meanings of the
* arguments passed. In this callback, @user is the x509_ctx,
* @in is the ssl pointer and @len is preverify_ok
* Notice that this callback maintains libwebsocket return
* conventions, return 0 to mean the cert is OK or 1 to fail it.
* This also means that if you don't handle this callback then
* the default callback action of returning 0 allows the client
* certificates.
*
* LWS_CALLBACK_CLIENT_APPEND_HANDSHAKE_HEADER: this callback happens
* when a client handshake is being compiled. @user is NULL,
* @in is a char **, it's pointing to a char * which holds the
* next location in the header buffer where you can add
* headers, and @len is the remaining space in the header buffer,
* which is typically some hundreds of bytes. So, to add a canned
* cookie, your handler code might look similar to:
*
* char **p = (char **)in;
*
* if (len < 100)
* return 1;
*
* *p += sprintf(*p, "Cookie: a=b\x0d\x0a");
*
* return 0;
*
* Notice if you add anything, you just have to take care about
* the CRLF on the line you added. Obviously this callback is
* optional, if you don't handle it everything is fine.
*
* Notice the callback is coming to protocols[0] all the time,
* because there is no specific protocol handshook yet.
*
* LWS_CALLBACK_CONFIRM_EXTENSION_OKAY: When the server handshake code
* sees that it does support a requested extension, before
* accepting the extension by additing to the list sent back to
* the client it gives this callback just to check that it's okay
* to use that extension. It calls back to the requested protocol
* and with @in being the extension name, @len is 0 and @user is
* valid. Note though at this time the ESTABLISHED callback hasn't
* happened yet so if you initialize @user content there, @user
* content during this callback might not be useful for anything.
* Notice this callback comes to protocols[0].
*
* LWS_CALLBACK_CLIENT_CONFIRM_EXTENSION_SUPPORTED: When a client
* connection is being prepared to start a handshake to a server,
* each supported extension is checked with protocols[0] callback
* with this reason, giving the user code a chance to suppress the
* claim to support that extension by returning non-zero. If
* unhandled, by default 0 will be returned and the extension
* support included in the header to the server. Notice this
* callback comes to protocols[0].
*
* LWS_CALLBACK_PROTOCOL_INIT: One-time call per protocol so it can
* do initial setup / allocations etc
*
* LWS_CALLBACK_PROTOCOL_DESTROY: One-time call per protocol indicating
* this protocol won't get used at all after this callback, the
* context is getting destroyed. Take the opportunity to
* deallocate everything that was allocated by the protocol.
*
* The next four reasons are optional and only need taking care of if you
* will be integrating libwebsockets sockets into an external polling
* array.
*
* LWS_CALLBACK_ADD_POLL_FD: libwebsocket deals with its poll() loop
* internally, but in the case you are integrating with another
* server you will need to have libwebsocket sockets share a
* polling array with the other server. This and the other
* POLL_FD related callbacks let you put your specialized
* poll array interface code in the callback for protocol 0, the
* first protocol you support, usually the HTTP protocol in the
* serving case. This callback happens when a socket needs to be
* added to the polling loop: @in contains the fd, and
* @len is the events bitmap (like, POLLIN). If you are using the
* internal polling loop (the "service" callback), you can just
* ignore these callbacks.
*
* LWS_CALLBACK_DEL_POLL_FD: This callback happens when a socket descriptor
* needs to be removed from an external polling array. @in is
* the socket desricptor. If you are using the internal polling
* loop, you can just ignore it.
*
* LWS_CALLBACK_SET_MODE_POLL_FD: This callback happens when libwebsockets
* wants to modify the events for the socket descriptor in @in.
* The handler should OR @len on to the events member of the pollfd
* struct for this socket descriptor. If you are using the
* internal polling loop, you can just ignore it.
*
* LWS_CALLBACK_CLEAR_MODE_POLL_FD: This callback occurs when libwebsockets
* wants to modify the events for the socket descriptor in @in.
* The handler should AND ~@len on to the events member of the
* pollfd struct for this socket descriptor. If you are using the
* internal polling loop, you can just ignore it.
*/
LWS_VISIBLE LWS_EXTERN int callback(struct libwebsocket_context *context,
struct libwebsocket *wsi,
enum libwebsocket_callback_reasons reason, void *user,
void *in, size_t len);
typedef int (callback_function)(struct libwebsocket_context *context,
struct libwebsocket *wsi,
enum libwebsocket_callback_reasons reason, void *user,
void *in, size_t len);
#ifndef LWS_NO_EXTENSIONS
/**
* extension_callback_function() - Hooks to allow extensions to operate
* @context: Websockets context
* @ext: This extension
* @wsi: Opaque websocket instance pointer
* @reason: The reason for the call
* @user: Pointer to per-session user data allocated by library
* @in: Pointer used for some callback reasons
* @len: Length set for some callback reasons
*
* Each extension that is active on a particular connection receives
* callbacks during the connection lifetime to allow the extension to
* operate on websocket data and manage itself.
*
* Libwebsockets takes care of allocating and freeing "user" memory for
* each active extension on each connection. That is what is pointed to
* by the @user parameter.
*
* LWS_EXT_CALLBACK_CONSTRUCT: called when the server has decided to
* select this extension from the list provided by the client,
* just before the server will send back the handshake accepting
* the connection with this extension active. This gives the
* extension a chance to initialize its connection context found
* in @user.
*
* LWS_EXT_CALLBACK_CLIENT_CONSTRUCT: same as LWS_EXT_CALLBACK_CONSTRUCT
* but called when client is instantiating this extension. Some
* extensions will work the same on client and server side and then
* you can just merge handlers for both CONSTRUCTS.
*
* LWS_EXT_CALLBACK_DESTROY: called when the connection the extension was
* being used on is about to be closed and deallocated. It's the
* last chance for the extension to deallocate anything it has
* allocated in the user data (pointed to by @user) before the
* user data is deleted. This same callback is used whether you
* are in client or server instantiation context.
*
* LWS_EXT_CALLBACK_PACKET_RX_PREPARSE: when this extension was active on
* a connection, and a packet of data arrived at the connection,
* it is passed to this callback to give the extension a chance to
* change the data, eg, decompress it. @user is pointing to the
* extension's private connection context data, @in is pointing
* to an lws_tokens struct, it consists of a char * pointer called
* token, and an int called token_len. At entry, these are
* set to point to the received buffer and set to the content
* length. If the extension will grow the content, it should use
* a new buffer allocated in its private user context data and
* set the pointed-to lws_tokens members to point to its buffer.
*
* LWS_EXT_CALLBACK_PACKET_TX_PRESEND: this works the same way as
* LWS_EXT_CALLBACK_PACKET_RX_PREPARSE above, except it gives the
* extension a chance to change websocket data just before it will
* be sent out. Using the same lws_token pointer scheme in @in,
* the extension can change the buffer and the length to be
* transmitted how it likes. Again if it wants to grow the
* buffer safely, it should copy the data into its own buffer and
* set the lws_tokens token pointer to it.
*/
LWS_VISIBLE LWS_EXTERN int extension_callback(struct libwebsocket_context *context,
struct libwebsocket_extension *ext,
struct libwebsocket *wsi,
enum libwebsocket_extension_callback_reasons reason,
void *user, void *in, size_t len);
typedef int (extension_callback_function)(struct libwebsocket_context *context,
struct libwebsocket_extension *ext,
struct libwebsocket *wsi,
enum libwebsocket_extension_callback_reasons reason,
void *user, void *in, size_t len);
#endif
/**
* struct libwebsocket_protocols - List of protocols and handlers server
* supports.
* @name: Protocol name that must match the one given in the client
* Javascript new WebSocket(url, 'protocol') name
* @callback: The service callback used for this protocol. It allows the
* service action for an entire protocol to be encapsulated in
* the protocol-specific callback
* @per_session_data_size: Each new connection using this protocol gets
* this much memory allocated on connection establishment and
* freed on connection takedown. A pointer to this per-connection
* allocation is passed into the callback in the 'user' parameter
* @rx_buffer_size: if you want atomic frames delivered to the callback, you
* should set this to the size of the biggest legal frame that
* you support. If the frame size is exceeded, there is no
* error, but the buffer will spill to the user callback when
* full, which you can detect by using
* libwebsockets_remaining_packet_payload(). Notice that you
* just talk about frame size here, the LWS_SEND_BUFFER_PRE_PADDING
* and post-padding are automatically also allocated on top.
* @owning_server: the server init call fills in this opaque pointer when
* registering this protocol with the server.
* @protocol_index: which protocol we are starting from zero
*
* This structure represents one protocol supported by the server. An
* array of these structures is passed to libwebsocket_create_server()
* allows as many protocols as you like to be handled by one server.
*/
struct libwebsocket_protocols {
const char *name;
callback_function *callback;
size_t per_session_data_size;
size_t rx_buffer_size;
/*
* below are filled in on server init and can be left uninitialized,
* no need for user to use them directly either
*/
struct libwebsocket_context *owning_server;
int protocol_index;
};
#ifndef LWS_NO_EXTENSIONS
/**
* struct libwebsocket_extension - An extension we know how to cope with
*
* @name: Formal extension name, eg, "deflate-stream"
* @callback: Service callback
* @per_session_data_size: Libwebsockets will auto-malloc this much
* memory for the use of the extension, a pointer
* to it comes in the @user callback parameter
* @per_context_private_data: Optional storage for this extension that
* is per-context, so it can track stuff across
* all sessions, etc, if it wants
*/
struct libwebsocket_extension {
const char *name;
extension_callback_function *callback;
size_t per_session_data_size;
void *per_context_private_data;
};
#endif
/**
* struct lws_context_creation_info: parameters to create context with
*
* @port: Port to listen on... you can use 0 to suppress listening on
* any port, that's what you want if you are not running a
* websocket server at all but just using it as a client
* @iface: NULL to bind the listen socket to all interfaces, or the
* interface name, eg, "eth2"
* @protocols: Array of structures listing supported protocols and a protocol-
* specific callback for each one. The list is ended with an
* entry that has a NULL callback pointer.
* It's not const because we write the owning_server member
* @extensions: NULL or array of libwebsocket_extension structs listing the
* extensions this context supports. If you configured with
* --without-extensions, you should give NULL here.
* @ssl_cert_filepath: If libwebsockets was compiled to use ssl, and you want
* to listen using SSL, set to the filepath to fetch the
* server cert from, otherwise NULL for unencrypted
* @ssl_private_key_filepath: filepath to private key if wanting SSL mode,
* else ignored
* @ssl_ca_filepath: CA certificate filepath or NULL
* @ssl_cipher_list: List of valid ciphers to use (eg,
* "RC4-MD5:RC4-SHA:AES128-SHA:AES256-SHA:HIGH:!DSS:!aNULL"
* or you can leave it as NULL to get "DEFAULT"
* @gid: group id to change to after setting listen socket, or -1.
* @uid: user id to change to after setting listen socket, or -1.
* @options: 0, or LWS_SERVER_OPTION_DEFEAT_CLIENT_MASK
* @user: optional user pointer that can be recovered via the context
* pointer using libwebsocket_context_user
* @ka_time: 0 for no keepalive, otherwise apply this keepalive timeout to
* all libwebsocket sockets, client or server
* @ka_probes: if ka_time was nonzero, after the timeout expires how many
* times to try to get a response from the peer before giving up
* and killing the connection
* @ka_interval: if ka_time was nonzero, how long to wait before each ka_probes
* attempt
*/
struct lws_context_creation_info {
int port;
const char *iface;
struct libwebsocket_protocols *protocols;
struct libwebsocket_extension *extensions;
const char *ssl_cert_filepath;
const char *ssl_private_key_filepath;
const char *ssl_ca_filepath;
const char *ssl_cipher_list;
int gid;
int uid;
unsigned int options;
void *user;
int ka_time;
int ka_probes;
int ka_interval;
};
LWS_VISIBLE LWS_EXTERN
void lws_set_log_level(int level,
void (*log_emit_function)(int level, const char *line));
LWS_VISIBLE LWS_EXTERN void
lwsl_emit_syslog(int level, const char *line);
LWS_VISIBLE LWS_EXTERN struct libwebsocket_context *
libwebsocket_create_context(struct lws_context_creation_info *info);
LWS_VISIBLE LWS_EXTERN void
libwebsocket_context_destroy(struct libwebsocket_context *context);
LWS_VISIBLE LWS_EXTERN int
libwebsocket_service(struct libwebsocket_context *context, int timeout_ms);
LWS_VISIBLE LWS_EXTERN int
libwebsocket_service_fd(struct libwebsocket_context *context,
struct pollfd *pollfd);
LWS_VISIBLE LWS_EXTERN void *
libwebsocket_context_user(struct libwebsocket_context *context);
/*
* IMPORTANT NOTICE!
*
* When sending with websocket protocol (LWS_WRITE_TEXT or LWS_WRITE_BINARY)
* the send buffer has to have LWS_SEND_BUFFER_PRE_PADDING bytes valid BEFORE
* buf, and LWS_SEND_BUFFER_POST_PADDING bytes valid AFTER (buf + len).
*
* This allows us to add protocol info before and after the data, and send as
* one packet on the network without payload copying, for maximum efficiency.
*
* So for example you need this kind of code to use libwebsocket_write with a
* 128-byte payload
*
* char buf[LWS_SEND_BUFFER_PRE_PADDING + 128 + LWS_SEND_BUFFER_POST_PADDING];
*
* // fill your part of the buffer... for example here it's all zeros
* memset(&buf[LWS_SEND_BUFFER_PRE_PADDING], 0, 128);
*
* libwebsocket_write(wsi, &buf[LWS_SEND_BUFFER_PRE_PADDING], 128,
* LWS_WRITE_TEXT);
*
* When sending LWS_WRITE_HTTP, there is no protocol addition and you can just
* use the whole buffer without taking care of the above.
*/
/*
* this is the frame nonce plus two header plus 8 length
* there's an additional two for mux extension per mux nesting level
* 2 byte prepend on close will already fit because control frames cannot use
* the big length style
*/
#define LWS_SEND_BUFFER_PRE_PADDING (4 + 10 + (2 * MAX_MUX_RECURSION))
#define LWS_SEND_BUFFER_POST_PADDING 4
LWS_VISIBLE LWS_EXTERN int
libwebsocket_write(struct libwebsocket *wsi, unsigned char *buf, size_t len,
enum libwebsocket_write_protocol protocol);
LWS_VISIBLE LWS_EXTERN int
libwebsockets_serve_http_file(struct libwebsocket_context *context,
struct libwebsocket *wsi, const char *file,
const char *content_type);
LWS_VISIBLE LWS_EXTERN int
libwebsockets_serve_http_file_fragment(struct libwebsocket_context *context,
struct libwebsocket *wsi);
LWS_VISIBLE LWS_EXTERN const struct libwebsocket_protocols *
libwebsockets_get_protocol(struct libwebsocket *wsi);
LWS_VISIBLE LWS_EXTERN int
libwebsocket_callback_on_writable(struct libwebsocket_context *context,
struct libwebsocket *wsi);
LWS_VISIBLE LWS_EXTERN int
libwebsocket_callback_on_writable_all_protocol(
const struct libwebsocket_protocols *protocol);
LWS_VISIBLE LWS_EXTERN int
libwebsocket_get_socket_fd(struct libwebsocket *wsi);
LWS_VISIBLE LWS_EXTERN int
libwebsocket_is_final_fragment(struct libwebsocket *wsi);
LWS_VISIBLE LWS_EXTERN unsigned char
libwebsocket_get_reserved_bits(struct libwebsocket *wsi);
LWS_VISIBLE LWS_EXTERN int
libwebsocket_rx_flow_control(struct libwebsocket *wsi, int enable);
LWS_VISIBLE LWS_EXTERN void
libwebsocket_rx_flow_allow_all_protocol(
const struct libwebsocket_protocols *protocol);
LWS_VISIBLE LWS_EXTERN size_t
libwebsockets_remaining_packet_payload(struct libwebsocket *wsi);
LWS_VISIBLE LWS_EXTERN struct libwebsocket *
libwebsocket_client_connect(struct libwebsocket_context *clients,
const char *address,
int port,
int ssl_connection,
const char *path,
const char *host,
const char *origin,
const char *protocol,
int ietf_version_or_minus_one);
LWS_VISIBLE LWS_EXTERN struct libwebsocket *
libwebsocket_client_connect_extended(struct libwebsocket_context *clients,
const char *address,
int port,
int ssl_connection,
const char *path,
const char *host,
const char *origin,
const char *protocol,
int ietf_version_or_minus_one,
void *userdata);
LWS_VISIBLE LWS_EXTERN const char *
libwebsocket_canonical_hostname(struct libwebsocket_context *context);
LWS_VISIBLE LWS_EXTERN void
libwebsockets_get_peer_addresses(struct libwebsocket_context *context,
struct libwebsocket *wsi, int fd, char *name, int name_len,
char *rip, int rip_len);
LWS_VISIBLE LWS_EXTERN int
libwebsockets_get_random(struct libwebsocket_context *context,
void *buf, int len);
LWS_VISIBLE LWS_EXTERN int
lws_daemonize(const char *_lock_path);
LWS_VISIBLE LWS_EXTERN int
lws_send_pipe_choked(struct libwebsocket *wsi);
LWS_VISIBLE LWS_EXTERN int
lws_frame_is_binary(struct libwebsocket *wsi);
LWS_VISIBLE LWS_EXTERN unsigned char *
libwebsockets_SHA1(const unsigned char *d, size_t n, unsigned char *md);
LWS_VISIBLE LWS_EXTERN int
lws_b64_encode_string(const char *in, int in_len, char *out, int out_size);
LWS_VISIBLE LWS_EXTERN int
lws_b64_decode_string(const char *in, char *out, int out_size);
LWS_VISIBLE LWS_EXTERN const char *
lws_get_library_version(void);
/* access to headers... only valid while headers valid */
LWS_VISIBLE LWS_EXTERN int
lws_hdr_total_length(struct libwebsocket *wsi, enum lws_token_indexes h);
LWS_VISIBLE LWS_EXTERN int
lws_hdr_copy(struct libwebsocket *wsi, char *dest, int len,
enum lws_token_indexes h);
/*
* Note: this is not normally needed as a user api. It's provided in case it is
* useful when integrating with other app poll loop service code.
*/
LWS_VISIBLE LWS_EXTERN int
libwebsocket_read(struct libwebsocket_context *context,
struct libwebsocket *wsi,
unsigned char *buf, size_t len);
#ifndef LWS_NO_EXTENSIONS
LWS_VISIBLE LWS_EXTERN struct libwebsocket_extension *libwebsocket_get_internal_extensions();
#endif
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,28 @@
#ifndef _GET_TIME_OF_DAY_H
#define _GET_TIME_OF_DAY_H
#ifdef __MINGW64__
#else
#ifdef __MINGW32__
#else
#include < time.h >
#endif
#endif
#include <windows.h> //I've ommited context line.
#if defined(_MSC_VER) || defined(_MSC_EXTENSIONS)
#define DELTA_EPOCH_IN_MICROSECS 11644473600000000Ui64
#else
#define DELTA_EPOCH_IN_MICROSECS 11644473600000000ULL
#endif
struct timezone
{
int tz_minuteswest; /* minutes W of Greenwich */
int tz_dsttime; /* type of dst correction */
};
int gettimeofday(struct timeval *tv, struct timezone *tz);
#endif

View File

@ -0,0 +1,62 @@
#ifndef __WEB_SOCK_W32_H__
#define __WEB_SOCK_W32_H__
// Windows uses _DEBUG and NDEBUG
#ifdef _DEBUG
#undef DEBUG
#define DEBUG 1
#endif
#pragma warning(disable : 4996)
#define bzero(b,len) (memset((b), '\0', (len)), (void) 0)
#define MSG_NOSIGNAL 0
#define SHUT_RDWR SD_BOTH
#define SOL_TCP IPPROTO_TCP
#define random rand
#define usleep _sleep
#ifdef __MINGW64__
#define DEF_POLL_STUFF
#endif
#ifdef __MINGW32__
#define DEF_POLL_STUFF
#endif
#ifdef DEF_POLL_STUFF
#include <winsock2.h>
typedef struct pollfd {
SOCKET fd;
short events;
short revents;
} WSAPOLLFD, *PWSAPOLLFD, *LPWSAPOLLFD;
#define POLLIN 0x0001 /* any readable data available */
#define POLLOUT 0x0004 /* file descriptor is writeable */
#define POLLERR 0x0008 /* some poll error occurred */
#define POLLHUP 0x0010 /* file descriptor was "hung up" */
#define POLLNVAL 0x0020 /* requested events "invalid" */
#endif
typedef INT (WSAAPI *PFNWSAPOLL)(LPWSAPOLLFD fdarray, ULONG nfds, INT timeout);
extern PFNWSAPOLL poll;
extern INT WSAAPI emulated_poll(LPWSAPOLLFD fdarray, ULONG nfds, INT timeout);
/* override configure because we are not using Makefiles */
#define LWS_NO_FORK
/* windows can't cope with this idea, needs assets in cwd */
#ifndef INSTALL_DATADIR
#define INSTALL_DATADIR "."
#endif
#endif

View File

@ -0,0 +1,526 @@
Libwebsockets and included programs are provided under the terms of the GNU
Library General Public License (LGPL) 2.1, with the following exceptions:
1) Static linking of programs with the libwebsockets library does not
constitute a derivative work and does not require the author to provide
source code for the program, use the shared libwebsockets libraries, or
link their program against a user-supplied version of libwebsockets.
If you link the program to a modified version of libwebsockets, then the
changes to libwebsockets must be provided under the terms of the LGPL in
sections 1, 2, and 4.
2) You do not have to provide a copy of the libwebsockets license with
programs that are linked to the libwebsockets library, nor do you have to
identify the libwebsockets license in your program or documentation as
required by section 6 of the LGPL.
However, programs must still identify their use of libwebsockets. The
following example statement can be included in user documentation to
satisfy this requirement:
"[program] is based in part on the work of the libwebsockets project
(http://libwebsockets.org)"
GNU LESSER GENERAL PUBLIC LICENSE
Version 2.1, February 1999
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
[This is the first released version of the Lesser GPL. It also counts
as the successor of the GNU Library Public License, version 2, hence
the version number 2.1.]
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
Licenses are intended to guarantee your freedom to share and change
free software--to make sure the software is free for all its users.
This license, the Lesser General Public License, applies to some
specially designated software packages--typically libraries--of the
Free Software Foundation and other authors who decide to use it. You
can use it too, but we suggest you first think carefully about whether
this license or the ordinary General Public License is the better
strategy to use in any particular case, based on the explanations below.
When we speak of free software, we are referring to freedom of use,
not price. Our General Public Licenses are designed to make sure that
you have the freedom to distribute copies of free software (and charge
for this service if you wish); that you receive source code or can get
it if you want it; that you can change the software and use pieces of
it in new free programs; and that you are informed that you can do
these things.
To protect your rights, we need to make restrictions that forbid
distributors to deny you these rights or to ask you to surrender these
rights. These restrictions translate to certain responsibilities for
you if you distribute copies of the library or if you modify it.
For example, if you distribute copies of the library, whether gratis
or for a fee, you must give the recipients all the rights that we gave
you. You must make sure that they, too, receive or can get the source
code. If you link other code with the library, you must provide
complete object files to the recipients, so that they can relink them
with the library after making changes to the library and recompiling
it. And you must show them these terms so they know their rights.
We protect your rights with a two-step method: (1) we copyright the
library, and (2) we offer you this license, which gives you legal
permission to copy, distribute and/or modify the library.
To protect each distributor, we want to make it very clear that
there is no warranty for the free library. Also, if the library is
modified by someone else and passed on, the recipients should know
that what they have is not the original version, so that the original
author's reputation will not be affected by problems that might be
introduced by others.
Finally, software patents pose a constant threat to the existence of
any free program. We wish to make sure that a company cannot
effectively restrict the users of a free program by obtaining a
restrictive license from a patent holder. Therefore, we insist that
any patent license obtained for a version of the library must be
consistent with the full freedom of use specified in this license.
Most GNU software, including some libraries, is covered by the
ordinary GNU General Public License. This license, the GNU Lesser
General Public License, applies to certain designated libraries, and
is quite different from the ordinary General Public License. We use
this license for certain libraries in order to permit linking those
libraries into non-free programs.
When a program is linked with a library, whether statically or using
a shared library, the combination of the two is legally speaking a
combined work, a derivative of the original library. The ordinary
General Public License therefore permits such linking only if the
entire combination fits its criteria of freedom. The Lesser General
Public License permits more lax criteria for linking other code with
the library.
We call this license the "Lesser" General Public License because it
does Less to protect the user's freedom than the ordinary General
Public License. It also provides other free software developers Less
of an advantage over competing non-free programs. These disadvantages
are the reason we use the ordinary General Public License for many
libraries. However, the Lesser license provides advantages in certain
special circumstances.
For example, on rare occasions, there may be a special need to
encourage the widest possible use of a certain library, so that it becomes
a de-facto standard. To achieve this, non-free programs must be
allowed to use the library. A more frequent case is that a free
library does the same job as widely used non-free libraries. In this
case, there is little to gain by limiting the free library to free
software only, so we use the Lesser General Public License.
In other cases, permission to use a particular library in non-free
programs enables a greater number of people to use a large body of
free software. For example, permission to use the GNU C Library in
non-free programs enables many more people to use the whole GNU
operating system, as well as its variant, the GNU/Linux operating
system.
Although the Lesser General Public License is Less protective of the
users' freedom, it does ensure that the user of a program that is
linked with the Library has the freedom and the wherewithal to run
that program using a modified version of the Library.
The precise terms and conditions for copying, distribution and
modification follow. Pay close attention to the difference between a
"work based on the library" and a "work that uses the library". The
former contains code derived from the library, whereas the latter must
be combined with the library in order to run.
GNU LESSER GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License Agreement applies to any software library or other
program which contains a notice placed by the copyright holder or
other authorized party saying it may be distributed under the terms of
this Lesser General Public License (also called "this License").
Each licensee is addressed as "you".
A "library" means a collection of software functions and/or data
prepared so as to be conveniently linked with application programs
(which use some of those functions and data) to form executables.
The "Library", below, refers to any such software library or work
which has been distributed under these terms. A "work based on the
Library" means either the Library or any derivative work under
copyright law: that is to say, a work containing the Library or a
portion of it, either verbatim or with modifications and/or translated
straightforwardly into another language. (Hereinafter, translation is
included without limitation in the term "modification".)
"Source code" for a work means the preferred form of the work for
making modifications to it. For a library, complete source code means
all the source code for all modules it contains, plus any associated
interface definition files, plus the scripts used to control compilation
and installation of the library.
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running a program using the Library is not restricted, and output from
such a program is covered only if its contents constitute a work based
on the Library (independent of the use of the Library in a tool for
writing it). Whether that is true depends on what the Library does
and what the program that uses the Library does.
1. You may copy and distribute verbatim copies of the Library's
complete source code as you receive it, in any medium, provided that
you conspicuously and appropriately publish on each copy an
appropriate copyright notice and disclaimer of warranty; keep intact
all the notices that refer to this License and to the absence of any
warranty; and distribute a copy of this License along with the
Library.
You may charge a fee for the physical act of transferring a copy,
and you may at your option offer warranty protection in exchange for a
fee.
2. You may modify your copy or copies of the Library or any portion
of it, thus forming a work based on the Library, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) The modified work must itself be a software library.
b) You must cause the files modified to carry prominent notices
stating that you changed the files and the date of any change.
c) You must cause the whole of the work to be licensed at no
charge to all third parties under the terms of this License.
d) If a facility in the modified Library refers to a function or a
table of data to be supplied by an application program that uses
the facility, other than as an argument passed when the facility
is invoked, then you must make a good faith effort to ensure that,
in the event an application does not supply such function or
table, the facility still operates, and performs whatever part of
its purpose remains meaningful.
(For example, a function in a library to compute square roots has
a purpose that is entirely well-defined independent of the
application. Therefore, Subsection 2d requires that any
application-supplied function or table used by this function must
be optional: if the application does not supply it, the square
root function must still compute square roots.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Library,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Library, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote
it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Library.
In addition, mere aggregation of another work not based on the Library
with the Library (or with a work based on the Library) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may opt to apply the terms of the ordinary GNU General Public
License instead of this License to a given copy of the Library. To do
this, you must alter all the notices that refer to this License, so
that they refer to the ordinary GNU General Public License, version 2,
instead of to this License. (If a newer version than version 2 of the
ordinary GNU General Public License has appeared, then you can specify
that version instead if you wish.) Do not make any other change in
these notices.
Once this change is made in a given copy, it is irreversible for
that copy, so the ordinary GNU General Public License applies to all
subsequent copies and derivative works made from that copy.
This option is useful when you wish to copy part of the code of
the Library into a program that is not a library.
4. You may copy and distribute the Library (or a portion or
derivative of it, under Section 2) in object code or executable form
under the terms of Sections 1 and 2 above provided that you accompany
it with the complete corresponding machine-readable source code, which
must be distributed under the terms of Sections 1 and 2 above on a
medium customarily used for software interchange.
If distribution of object code is made by offering access to copy
from a designated place, then offering equivalent access to copy the
source code from the same place satisfies the requirement to
distribute the source code, even though third parties are not
compelled to copy the source along with the object code.
5. A program that contains no derivative of any portion of the
Library, but is designed to work with the Library by being compiled or
linked with it, is called a "work that uses the Library". Such a
work, in isolation, is not a derivative work of the Library, and
therefore falls outside the scope of this License.
However, linking a "work that uses the Library" with the Library
creates an executable that is a derivative of the Library (because it
contains portions of the Library), rather than a "work that uses the
library". The executable is therefore covered by this License.
Section 6 states terms for distribution of such executables.
When a "work that uses the Library" uses material from a header file
that is part of the Library, the object code for the work may be a
derivative work of the Library even though the source code is not.
Whether this is true is especially significant if the work can be
linked without the Library, or if the work is itself a library. The
threshold for this to be true is not precisely defined by law.
If such an object file uses only numerical parameters, data
structure layouts and accessors, and small macros and small inline
functions (ten lines or less in length), then the use of the object
file is unrestricted, regardless of whether it is legally a derivative
work. (Executables containing this object code plus portions of the
Library will still fall under Section 6.)
Otherwise, if the work is a derivative of the Library, you may
distribute the object code for the work under the terms of Section 6.
Any executables containing that work also fall under Section 6,
whether or not they are linked directly with the Library itself.
6. As an exception to the Sections above, you may also combine or
link a "work that uses the Library" with the Library to produce a
work containing portions of the Library, and distribute that work
under terms of your choice, provided that the terms permit
modification of the work for the customer's own use and reverse
engineering for debugging such modifications.
You must give prominent notice with each copy of the work that the
Library is used in it and that the Library and its use are covered by
this License. You must supply a copy of this License. If the work
during execution displays copyright notices, you must include the
copyright notice for the Library among them, as well as a reference
directing the user to the copy of this License. Also, you must do one
of these things:
a) Accompany the work with the complete corresponding
machine-readable source code for the Library including whatever
changes were used in the work (which must be distributed under
Sections 1 and 2 above); and, if the work is an executable linked
with the Library, with the complete machine-readable "work that
uses the Library", as object code and/or source code, so that the
user can modify the Library and then relink to produce a modified
executable containing the modified Library. (It is understood
that the user who changes the contents of definitions files in the
Library will not necessarily be able to recompile the application
to use the modified definitions.)
b) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (1) uses at run time a
copy of the library already present on the user's computer system,
rather than copying library functions into the executable, and (2)
will operate properly with a modified version of the library, if
the user installs one, as long as the modified version is
interface-compatible with the version that the work was made with.
c) Accompany the work with a written offer, valid for at
least three years, to give the same user the materials
specified in Subsection 6a, above, for a charge no more
than the cost of performing this distribution.
d) If distribution of the work is made by offering access to copy
from a designated place, offer equivalent access to copy the above
specified materials from the same place.
e) Verify that the user has already received a copy of these
materials or that you have already sent this user a copy.
For an executable, the required form of the "work that uses the
Library" must include any data and utility programs needed for
reproducing the executable from it. However, as a special exception,
the materials to be distributed need not include anything that is
normally distributed (in either source or binary form) with the major
components (compiler, kernel, and so on) of the operating system on
which the executable runs, unless that component itself accompanies
the executable.
It may happen that this requirement contradicts the license
restrictions of other proprietary libraries that do not normally
accompany the operating system. Such a contradiction means you cannot
use both them and the Library together in an executable that you
distribute.
7. You may place library facilities that are a work based on the
Library side-by-side in a single library together with other library
facilities not covered by this License, and distribute such a combined
library, provided that the separate distribution of the work based on
the Library and of the other library facilities is otherwise
permitted, and provided that you do these two things:
a) Accompany the combined library with a copy of the same work
based on the Library, uncombined with any other library
facilities. This must be distributed under the terms of the
Sections above.
b) Give prominent notice with the combined library of the fact
that part of it is a work based on the Library, and explaining
where to find the accompanying uncombined form of the same work.
8. You may not copy, modify, sublicense, link with, or distribute
the Library except as expressly provided under this License. Any
attempt otherwise to copy, modify, sublicense, link with, or
distribute the Library is void, and will automatically terminate your
rights under this License. However, parties who have received copies,
or rights, from you under this License will not have their licenses
terminated so long as such parties remain in full compliance.
9. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Library or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Library (or any work based on the
Library), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Library or works based on it.
10. Each time you redistribute the Library (or any work based on the
Library), the recipient automatically receives a license from the
original licensor to copy, distribute, link with or modify the Library
subject to these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties with
this License.
11. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Library at all. For example, if a patent
license would not permit royalty-free redistribution of the Library by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Library.
If any portion of this section is held invalid or unenforceable under any
particular circumstance, the balance of the section is intended to apply,
and the section as a whole is intended to apply in other circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
12. If the distribution and/or use of the Library is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Library under this License may add
an explicit geographical distribution limitation excluding those countries,
so that distribution is permitted only in or among countries not thus
excluded. In such case, this License incorporates the limitation as if
written in the body of this License.
13. The Free Software Foundation may publish revised and/or new
versions of the Lesser General Public License from time to time.
Such new versions will be similar in spirit to the present version,
but may differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the Library
specifies a version number of this License which applies to it and
"any later version", you have the option of following the terms and
conditions either of that version or of any later version published by
the Free Software Foundation. If the Library does not specify a
license version number, you may choose any version ever published by
the Free Software Foundation.
14. If you wish to incorporate parts of the Library into other free
programs whose distribution conditions are incompatible with these,
write to the author to ask for permission. For software which is
copyrighted by the Free Software Foundation, write to the Free
Software Foundation; we sometimes make exceptions for this. Our
decision will be guided by the two goals of preserving the free status
of all derivatives of our free software and of promoting the sharing
and reuse of software generally.
NO WARRANTY
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Libraries
If you develop a new library, and you want it to be of the greatest
possible use to the public, we recommend making it free software that
everyone can redistribute and change. You can do so by permitting
redistribution under these terms (or, alternatively, under the terms of the
ordinary General Public License).
To apply these terms, attach the following notices to the library. It is
safest to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least the
"copyright" line and a pointer to where the full notice is found.
<one line to give the library's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Also add information on how to contact you by electronic and paper mail.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the library, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the
library `Frob' (a library for tweaking knobs) written by James Random Hacker.
<signature of Ty Coon>, 1 April 1990
Ty Coon, President of Vice
That's all there is to it!

View File

@ -55,6 +55,7 @@ Classes/ExtensionsTest/CocosBuilderTest/MenuTest/MenuTestLayer.cpp \
Classes/ExtensionsTest/CocosBuilderTest/AnimationsTest/AnimationsTestLayer.cpp \
Classes/ExtensionsTest/CocosBuilderTest/TimelineCallbackTest/TimelineCallbackTestLayer.cpp \
Classes/ExtensionsTest/NetworkTest/HttpClientTest.cpp \
Classes/ExtensionsTest/NetworkTest/WebSocketTest.cpp \
Classes/ExtensionsTest/EditBoxTest/EditBoxTest.cpp \
Classes/ExtensionsTest/TableViewTest/TableViewTestScene.cpp \
Classes/ExtensionsTest/TableViewTest/CustomTableViewCell.cpp \

View File

@ -8,6 +8,10 @@
#endif
#include "TableViewTest/TableViewTestScene.h"
#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS) || (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) || (CC_TARGET_PLATFORM == CC_PLATFORM_WIN32)
#include "NetworkTest/WebSocketTest.h"
#endif
#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS) || (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) || (CC_TARGET_PLATFORM == CC_PLATFORM_MAC) || (CC_TARGET_PLATFORM == CC_PLATFORM_WIN32) || (CC_TARGET_PLATFORM == CC_PLATFORM_TIZEN)
#include "EditBoxTest/EditBoxTest.h"
#endif
@ -24,6 +28,9 @@ enum
TEST_CCCONTROLBUTTON,
TEST_COCOSBUILDER,
TEST_HTTPCLIENT,
#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS) || (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) || (CC_TARGET_PLATFORM == CC_PLATFORM_WIN32)
TEST_WEBSOCKET,
#endif
#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS) || (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) || (CC_TARGET_PLATFORM == CC_PLATFORM_MAC) || (CC_TARGET_PLATFORM == CC_PLATFORM_WIN32) || (CC_TARGET_PLATFORM == CC_PLATFORM_TIZEN)
TEST_EDITBOX,
#endif
@ -39,6 +46,9 @@ static const std::string testsName[TEST_MAX_COUNT] =
#if (CC_TARGET_PLATFORM != CC_PLATFORM_EMSCRIPTEN)
"HttpClientTest",
#endif
#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS) || (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) || (CC_TARGET_PLATFORM == CC_PLATFORM_WIN32)
"WebSocketTest",
#endif
#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS) || (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) || (CC_TARGET_PLATFORM == CC_PLATFORM_MAC) || (CC_TARGET_PLATFORM == CC_PLATFORM_WIN32) || (CC_TARGET_PLATFORM == CC_PLATFORM_TIZEN)
"EditBoxTest",
#endif
@ -109,6 +119,13 @@ void ExtensionsMainLayer::menuCallback(CCObject* pSender)
}
break;
#endif
#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS) || (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) || (CC_TARGET_PLATFORM == CC_PLATFORM_WIN32)
case TEST_WEBSOCKET:
{
runWebSocketTest();
}
break;
#endif
#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS) || (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) || (CC_TARGET_PLATFORM == CC_PLATFORM_MAC) || (CC_TARGET_PLATFORM == CC_PLATFORM_WIN32) || (CC_TARGET_PLATFORM == CC_PLATFORM_TIZEN)
case TEST_EDITBOX:
{

View File

@ -0,0 +1,241 @@
//
// WebSocketTest.cpp
// TestCpp
//
// Created by James Chen on 5/31/13.
//
//
#include "WebSocketTest.h"
#include "../ExtensionsTest.h"
USING_NS_CC;
USING_NS_CC_EXT;
WebSocketTestLayer::WebSocketTestLayer()
: _wsiSendText(NULL)
, _wsiSendBinary(NULL)
, _wsiError(NULL)
, _sendTextStatus(NULL)
, _sendBinaryStatus(NULL)
, _errorStatus(NULL)
, _sendTextTimes(0)
, _sendBinaryTimes(0)
{
CCSize winSize = CCDirector::sharedDirector()->getWinSize();
const int MARGIN = 40;
const int SPACE = 35;
CCLabelTTF *label = CCLabelTTF::create("WebSocket Test", "Arial", 28);
label->setPosition(ccp(winSize.width / 2, winSize.height - MARGIN));
addChild(label, 0);
CCMenu *menuRequest = CCMenu::create();
menuRequest->setPosition(CCPointZero);
addChild(menuRequest);
// Send Text
CCLabelTTF *labelSendText = CCLabelTTF::create("Send Text", "Arial", 22);
CCMenuItemLabel *itemSendText = CCMenuItemLabel::create(labelSendText, this, menu_selector(WebSocketTestLayer::onMenuSendTextClicked));
itemSendText->setPosition(ccp(winSize.width / 2, winSize.height - MARGIN - SPACE));
menuRequest->addChild(itemSendText);
// Send Binary
CCLabelTTF *labelSendBinary = CCLabelTTF::create("Send Binary", "Arial", 22);
CCMenuItemLabel *itemSendBinary = CCMenuItemLabel::create(labelSendBinary, this, menu_selector(WebSocketTestLayer::onMenuSendBinaryClicked));
itemSendBinary->setPosition(ccp(winSize.width / 2, winSize.height - MARGIN - 2 * SPACE));
menuRequest->addChild(itemSendBinary);
// Send Text Status Label
_sendTextStatus = CCLabelTTF::create("Send Text WS is waiting...", "Arial", 14, CCSizeMake(160, 100), kCCTextAlignmentCenter, kCCVerticalTextAlignmentTop);
_sendTextStatus->setAnchorPoint(ccp(0, 0));
_sendTextStatus->setPosition(ccp(VisibleRect::left().x, VisibleRect::rightBottom().y + 25));
this->addChild(_sendTextStatus);
// Send Binary Status Label
_sendBinaryStatus = CCLabelTTF::create("Send Binary WS is waiting...", "Arial", 14, CCSizeMake(160, 100), kCCTextAlignmentCenter, kCCVerticalTextAlignmentTop);
_sendBinaryStatus->setAnchorPoint(ccp(0, 0));
_sendBinaryStatus->setPosition(ccp(VisibleRect::left().x + 160, VisibleRect::rightBottom().y + 25));
this->addChild(_sendBinaryStatus);
// Error Label
_errorStatus = CCLabelTTF::create("Error WS is waiting...", "Arial", 14, CCSizeMake(160, 100), kCCTextAlignmentCenter, kCCVerticalTextAlignmentTop);
_errorStatus->setAnchorPoint(ccp(0, 0));
_errorStatus->setPosition(ccp(VisibleRect::left().x + 320, VisibleRect::rightBottom().y + 25));
this->addChild(_errorStatus);
// Back Menu
CCMenuItemFont *itemBack = CCMenuItemFont::create("Back", this, menu_selector(WebSocketTestLayer::toExtensionsMainLayer));
itemBack->setPosition(ccp(VisibleRect::rightBottom().x - 50, VisibleRect::rightBottom().y + 25));
CCMenu *menuBack = CCMenu::create(itemBack, NULL);
menuBack->setPosition(CCPointZero);
addChild(menuBack);
_wsiSendText = new WebSocket();
_wsiSendBinary = new WebSocket();
_wsiError = new WebSocket();
if (!_wsiSendText->init(*this, "ws://echo.websocket.org"))
{
CC_SAFE_DELETE(_wsiSendText);
}
if (!_wsiSendBinary->init(*this, "ws://echo.websocket.org"))
{
CC_SAFE_DELETE(_wsiSendBinary);
}
if (!_wsiError->init(*this, "ws://invalid.url.com"))
{
CC_SAFE_DELETE(_wsiError);
}
}
WebSocketTestLayer::~WebSocketTestLayer()
{
if (_wsiSendText)
_wsiSendText->close();
if (_wsiSendBinary)
_wsiSendBinary->close();
if (_wsiError)
_wsiError->close();
}
// Delegate methods
void WebSocketTestLayer::onOpen(cocos2d::extension::WebSocket* ws)
{
CCLog("Websocket (%p) opened", ws);
if (ws == _wsiSendText)
{
_sendTextStatus->setString("Send Text WS was opened.");
}
else if (ws == _wsiSendBinary)
{
_sendBinaryStatus->setString("Send Binary WS was opened.");
}
else if (ws == _wsiError)
{
CCAssert(0, "error test will never go here.");
}
}
void WebSocketTestLayer::onMessage(cocos2d::extension::WebSocket* ws, const cocos2d::extension::WebSocket::Data& data)
{
if (!data.isBinary)
{
_sendTextTimes++;
char times[100] = {0};
sprintf(times, "%d", _sendTextTimes);
std::string textStr = std::string("response text msg: ")+data.bytes+", "+times;
CCLog("%s", textStr.c_str());
_sendTextStatus->setString(textStr.c_str());
}
else
{
_sendBinaryTimes++;
char times[100] = {0};
sprintf(times, "%d", _sendBinaryTimes);
std::string binaryStr = "response bin msg: ";
for (int i = 0; i < data.len; ++i) {
if (data.bytes[i] != '\0')
{
binaryStr += data.bytes[i];
}
else
{
binaryStr += "\'\\0\'";
}
}
binaryStr += std::string(", ")+times;
CCLog("%s", binaryStr.c_str());
_sendBinaryStatus->setString(binaryStr.c_str());
}
}
void WebSocketTestLayer::onClose(cocos2d::extension::WebSocket* ws)
{
CCLog("websocket instance (%p) closed.", ws);
if (ws == _wsiSendText)
{
_wsiSendText = NULL;
}
else if (ws == _wsiSendBinary)
{
_wsiSendBinary = NULL;
}
else if (ws == _wsiError)
{
_wsiError = NULL;
}
// Delete websocket instance.
CC_SAFE_DELETE(ws);
}
void WebSocketTestLayer::onError(cocos2d::extension::WebSocket* ws, const cocos2d::extension::WebSocket::ErrorCode& error)
{
CCLog("Error was fired, error code: %d", error);
if (ws == _wsiError)
{
char buf[100] = {0};
sprintf(buf, "an error was fired, code: %d", error);
_errorStatus->setString(buf);
}
}
void WebSocketTestLayer::toExtensionsMainLayer(cocos2d::CCObject *sender)
{
ExtensionsTestScene *pScene = new ExtensionsTestScene();
pScene->runThisTest();
pScene->release();
}
// Menu Callbacks
void WebSocketTestLayer::onMenuSendTextClicked(cocos2d::CCObject *sender)
{
if (_wsiSendText->getReadyState() == WebSocket::kStateOpen)
{
_sendTextStatus->setString("Send Text WS is waiting...");
_wsiSendText->send("Hello WebSocket, I'm a text message.");
}
else
{
std::string warningStr = "send text websocket instance wasn't ready...";
CCLog("%s", warningStr.c_str());
_sendTextStatus->setString(warningStr.c_str());
}
}
void WebSocketTestLayer::onMenuSendBinaryClicked(cocos2d::CCObject *sender)
{
if (_wsiSendBinary->getReadyState() == WebSocket::kStateOpen)
{
_sendBinaryStatus->setString("Send Binary WS is waiting...");
char buf[] = "Hello WebSocket,\0 I'm\0 a\0 binary\0 message\0.";
_wsiSendBinary->send((unsigned char*)buf, sizeof(buf));
}
else
{
std::string warningStr = "send binary websocket instance wasn't ready...";
CCLog("%s", warningStr.c_str());
_sendBinaryStatus->setString(warningStr.c_str());
}
}
void runWebSocketTest()
{
CCScene *pScene = CCScene::create();
WebSocketTestLayer *pLayer = new WebSocketTestLayer();
pScene->addChild(pLayer);
CCDirector::sharedDirector()->replaceScene(pScene);
pLayer->release();
}

View File

@ -0,0 +1,50 @@
//
// WebSocketTest.h
// TestCpp
//
// Created by James Chen on 5/31/13.
//
//
#ifndef __TestCpp__WebSocketTest__
#define __TestCpp__WebSocketTest__
#include "cocos2d.h"
#include "cocos-ext.h"
#include "WebSocket.h"
class WebSocketTestLayer
: public cocos2d::CCLayer
, public cocos2d::extension::WebSocket::Delegate
{
public:
WebSocketTestLayer();
virtual ~WebSocketTestLayer();
virtual void onOpen(cocos2d::extension::WebSocket* ws);
virtual void onMessage(cocos2d::extension::WebSocket* ws, const cocos2d::extension::WebSocket::Data& data);
virtual void onClose(cocos2d::extension::WebSocket* ws);
virtual void onError(cocos2d::extension::WebSocket* ws, const cocos2d::extension::WebSocket::ErrorCode& error);
void toExtensionsMainLayer(cocos2d::CCObject *sender);
// Menu Callbacks
void onMenuSendTextClicked(cocos2d::CCObject *sender);
void onMenuSendBinaryClicked(cocos2d::CCObject *sender);
private:
cocos2d::extension::WebSocket* _wsiSendText;
cocos2d::extension::WebSocket* _wsiSendBinary;
cocos2d::extension::WebSocket* _wsiError;
cocos2d::CCLabelTTF* _sendTextStatus;
cocos2d::CCLabelTTF* _sendBinaryStatus;
cocos2d::CCLabelTTF* _errorStatus;
int _sendTextTimes;
int _sendBinaryTimes;
};
void runWebSocketTest();
#endif /* defined(__TestCpp__WebSocketTest__) */

View File

@ -1 +1 @@
c263309fadbcba0104099bb226f0dc701522c6d1
c12820b10f5bb33955c15eaf4cae17a4628455f8

View File

@ -65,7 +65,7 @@
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>$(ProjectDir)..\..\..\..\cocos2dx;$(ProjectDir)..\..\..\..\cocos2dx\include;$(ProjectDir)..\..\..\..\cocos2dx\kazmath\include;$(ProjectDir)..\..\..\..\cocos2dx\platform\win32;$(ProjectDir)..\..\..\..\cocos2dx\platform\third_party\win32;$(ProjectDir)..\..\..\..\cocos2dx\platform\third_party\win32\OGLES;$(ProjectDir)..\..\..\..\external;$(ProjectDir)..\..\..\..\external\chipmunk\include\chipmunk;$(ProjectDir)..\..\..\..\CocosDenshion\include;$(ProjectDir)..\..\..\..\extensions;..\Classes;..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>$(ProjectDir)..\..\..\..\cocos2dx;$(ProjectDir)..\..\..\..\cocos2dx\include;$(ProjectDir)..\..\..\..\cocos2dx\kazmath\include;$(ProjectDir)..\..\..\..\cocos2dx\platform\win32;$(ProjectDir)..\..\..\..\cocos2dx\platform\third_party\win32;$(ProjectDir)..\..\..\..\cocos2dx\platform\third_party\win32\OGLES;$(ProjectDir)..\..\..\..\cocos2dx\platform\third_party\win32\pthread;$(ProjectDir)..\..\..\..\external;$(ProjectDir)..\..\..\..\external\chipmunk\include\chipmunk;$(ProjectDir)..\..\..\..\external\libwebsockets\win32\include;$(ProjectDir)..\..\..\..\CocosDenshion\include;$(ProjectDir)..\..\..\..\extensions;$(ProjectDir)..\..\..\..\extensions\network;..\Classes;..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USE_MATH_DEFINES;GL_GLEXT_PROTOTYPES;CC_ENABLE_CHIPMUNK_INTEGRATION=1;COCOS2D_DEBUG=1;_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>true</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
@ -77,7 +77,7 @@
<DisableSpecificWarnings>4267;4251;4244;%(DisableSpecificWarnings)</DisableSpecificWarnings>
</ClCompile>
<Link>
<AdditionalDependencies>libExtensions.lib;libcocos2d.lib;libCocosDenshion.lib;opengl32.lib;glew32.lib;libBox2d.lib;libchipmunk.lib;libcurl_imp.lib;pthreadVCE2.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>libExtensions.lib;libcocos2d.lib;libCocosDenshion.lib;opengl32.lib;glew32.lib;libBox2d.lib;libchipmunk.lib;libcurl_imp.lib;websockets.lib;pthreadVCE2.lib;%(AdditionalDependencies)</AdditionalDependencies>
<OutputFile>$(OutDir)$(ProjectName).exe</OutputFile>
<AdditionalLibraryDirectories>$(OutDir);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<GenerateDebugInformation>true</GenerateDebugInformation>
@ -88,12 +88,17 @@
<Command>
</Command>
</PostBuildEvent>
<PreLinkEvent>
<Command>if not exist "$(OutDir)" mkdir "$(OutDir)"
xcopy /Y /Q "$(ProjectDir)..\..\..\..\external\libwebsockets\win32\lib\*.*" "$(OutDir)"
</Command>
</PreLinkEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<Optimization>MaxSpeed</Optimization>
<IntrinsicFunctions>true</IntrinsicFunctions>
<AdditionalIncludeDirectories>$(ProjectDir)..\..\..\..\cocos2dx;$(ProjectDir)..\..\..\..\cocos2dx\include;$(ProjectDir)..\..\..\..\cocos2dx\kazmath\include;$(ProjectDir)..\..\..\..\cocos2dx\platform\win32;$(ProjectDir)..\..\..\..\cocos2dx\platform\third_party\win32;$(ProjectDir)..\..\..\..\cocos2dx\platform\third_party\win32\OGLES;$(ProjectDir)..\..\..\..\external;$(ProjectDir)..\..\..\..\external\chipmunk\include\chipmunk;$(ProjectDir)..\..\..\..\CocosDenshion\include;$(ProjectDir)..\..\..\..\extensions;..\Classes;..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>$(ProjectDir)..\..\..\..\cocos2dx;$(ProjectDir)..\..\..\..\cocos2dx\include;$(ProjectDir)..\..\..\..\cocos2dx\kazmath\include;$(ProjectDir)..\..\..\..\cocos2dx\platform\win32;$(ProjectDir)..\..\..\..\cocos2dx\platform\third_party\win32;$(ProjectDir)..\..\..\..\cocos2dx\platform\third_party\win32\OGLES;$(ProjectDir)..\..\..\..\cocos2dx\platform\third_party\win32\pthread;$(ProjectDir)..\..\..\..\external;$(ProjectDir)..\..\..\..\external\chipmunk\include\chipmunk;$(ProjectDir)..\..\..\..\external\libwebsockets\win32\include;$(ProjectDir)..\..\..\..\CocosDenshion\include;$(ProjectDir)..\..\..\..\extensions;$(ProjectDir)..\..\..\..\extensions\network;..\Classes;..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USE_MATH_DEFINES;GL_GLEXT_PROTOTYPES;CC_ENABLE_CHIPMUNK_INTEGRATION=1;_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>
@ -104,7 +109,7 @@
<DisableSpecificWarnings>4267;4251;4244;%(DisableSpecificWarnings)</DisableSpecificWarnings>
</ClCompile>
<Link>
<AdditionalDependencies>libcocos2d.lib;libCocosDenshion.lib;opengl32.lib;glew32.lib;libBox2d.lib;libchipmunk.lib;libcurl_imp.lib;libExtensions.lib;pthreadVCE2.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>libExtensions.lib;libcocos2d.lib;libCocosDenshion.lib;opengl32.lib;glew32.lib;libBox2d.lib;libchipmunk.lib;libcurl_imp.lib;websockets.lib;pthreadVCE2.lib;%(AdditionalDependencies)</AdditionalDependencies>
<OutputFile>$(OutDir)$(ProjectName).exe</OutputFile>
<AdditionalLibraryDirectories>$(OutDir);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<GenerateDebugInformation>true</GenerateDebugInformation>
@ -117,6 +122,11 @@
<Command>
</Command>
</PostBuildEvent>
<PreLinkEvent>
<Command>if not exist "$(OutDir)" mkdir "$(OutDir)"
xcopy /Y /Q "$(ProjectDir)..\..\..\..\external\libwebsockets\win32\lib\*.*" "$(OutDir)"
</Command>
</PreLinkEvent>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\Classes\ChipmunkTest\ChipmunkTest.cpp" />
@ -129,6 +139,7 @@
<ClCompile Include="..\Classes\ExtensionsTest\ControlExtensionTest\CCControlStepperTest\CCControlStepperTest.cpp" />
<ClCompile Include="..\Classes\ExtensionsTest\EditBoxTest\EditBoxTest.cpp" />
<ClCompile Include="..\Classes\ExtensionsTest\NetworkTest\HttpClientTest.cpp" />
<ClCompile Include="..\Classes\ExtensionsTest\NetworkTest\WebSocketTest.cpp" />
<ClCompile Include="..\Classes\ExtensionsTest\TableViewTest\CustomTableViewCell.cpp" />
<ClCompile Include="..\Classes\ExtensionsTest\TableViewTest\TableViewTestScene.cpp" />
<ClCompile Include="..\Classes\FileUtilsTest\FileUtilsTest.cpp" />
@ -227,6 +238,7 @@
<ClInclude Include="..\Classes\ExtensionsTest\ControlExtensionTest\CCControlStepperTest\CCControlStepperTest.h" />
<ClInclude Include="..\Classes\ExtensionsTest\EditBoxTest\EditBoxTest.h" />
<ClInclude Include="..\Classes\ExtensionsTest\NetworkTest\HttpClientTest.h" />
<ClInclude Include="..\Classes\ExtensionsTest\NetworkTest\WebSocketTest.h" />
<ClInclude Include="..\Classes\ExtensionsTest\TableViewTest\CustomTableViewCell.h" />
<ClInclude Include="..\Classes\ExtensionsTest\TableViewTest\TableViewTestScene.h" />
<ClInclude Include="..\Classes\FileUtilsTest\FileUtilsTest.h" />

View File

@ -510,6 +510,9 @@
<ClCompile Include="..\Classes\ConfigurationTest\ConfigurationTest.cpp">
<Filter>Classes\ConfigurationTest</Filter>
</ClCompile>
<ClCompile Include="..\Classes\ExtensionsTest\NetworkTest\WebSocketTest.cpp">
<Filter>Classes\ExtensionsTest\NetworkTest</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="main.h">
@ -974,5 +977,8 @@
<ClInclude Include="..\Classes\ConfigurationTest\ConfigurationTest.h">
<Filter>Classes\ConfigurationTest</Filter>
</ClInclude>
<ClInclude Include="..\Classes\ExtensionsTest\NetworkTest\WebSocketTest.h">
<Filter>Classes\ExtensionsTest\NetworkTest</Filter>
</ClInclude>
</ItemGroup>
</Project>

@ -1 +1 @@
Subproject commit 91d853f5c72df3137e2f3eb68229b426a3252e5d
Subproject commit 568f0addf94b132938892a33eb83dc5e7149110b

View File

@ -11,8 +11,10 @@
#include "js_bindings_system_registration.h"
#include "jsb_opengl_registration.h"
#include "XMLHTTPRequest.h"
#include "jsb_websocket.h"
USING_NS_CC;
USING_NS_CC_EXT;
using namespace CocosDenshion;
AppDelegate::AppDelegate()
@ -45,6 +47,7 @@ bool AppDelegate::applicationDidFinishLaunching()
sc->addRegisterCallback(JSB_register_opengl);
sc->addRegisterCallback(jsb_register_system);
sc->addRegisterCallback(MinXmlHttpRequest::_js_register);
sc->addRegisterCallback(register_jsb_websocket);
sc->start();

View File

@ -1 +1 @@
58bdb54b5e8ea28b2382bd97ecc4bbd3fd60bba1
ccb7f062be010df9d1b6be60ac35b8f01f742ced

View File

@ -94,10 +94,11 @@
<PreLinkEvent>
<Command>if not exist "$(OutDir)" mkdir "$(OutDir)"
xcopy /Y /Q "$(ProjectDir)..\..\..\..\scripting\javascript\spidermonkey-win32\lib\*.*" "$(OutDir)"
xcopy /Y /Q "$(ProjectDir)..\..\..\..\external\libwebsockets\win32\lib\*.*" "$(OutDir)"
</Command>
</PreLinkEvent>
<Link>
<AdditionalDependencies>libcocos2d.lib;libExtensions.lib;opengl32.lib;glew32.lib;libCocosDenshion.lib;libchipmunk.lib;libJSBinding.lib;libcurl_imp.lib;mozjs.lib;ws2_32.lib;sqlite3.lib;pthreadVCE2.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>libcocos2d.lib;libExtensions.lib;opengl32.lib;glew32.lib;libCocosDenshion.lib;libchipmunk.lib;libJSBinding.lib;libcurl_imp.lib;mozjs.lib;ws2_32.lib;sqlite3.lib;pthreadVCE2.lib;websockets.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>$(OutDir);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Windows</SubSystem>
@ -148,10 +149,11 @@ xcopy "$(ProjectDir)..\..\Shared\tests" "$(OutDir)\TestJavascriptRes\" /e /Y</Co
<PreLinkEvent>
<Command>if not exist "$(OutDir)" mkdir "$(OutDir)"
xcopy /Y /Q "$(ProjectDir)..\..\..\..\scripting\javascript\spidermonkey-win32\lib\*.*" "$(OutDir)"
xcopy /Y /Q "$(ProjectDir)..\..\..\..\external\libwebsockets\win32\lib\*.*" "$(OutDir)"
</Command>
</PreLinkEvent>
<Link>
<AdditionalDependencies>libcocos2d.lib;libExtensions.lib;opengl32.lib;glew32.lib;libCocosDenshion.lib;libchipmunk.lib;libJSBinding.lib;libcurl_imp.lib;mozjs.lib;ws2_32.lib;sqlite3.lib;pthreadVCE2.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>libcocos2d.lib;libExtensions.lib;opengl32.lib;glew32.lib;libCocosDenshion.lib;libchipmunk.lib;libJSBinding.lib;libcurl_imp.lib;mozjs.lib;ws2_32.lib;sqlite3.lib;pthreadVCE2.lib;websockets.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>$(OutDir);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<SubSystem>Windows</SubSystem>
<TargetMachine>MachineX86</TargetMachine>

View File

@ -25,7 +25,8 @@ LOCAL_SRC_FILES := ScriptingCore.cpp \
jsb_opengl_registration.cpp \
generated/jsb_cocos2dx_auto.cpp \
generated/jsb_cocos2dx_extension_auto.cpp \
XMLHTTPRequest.cpp
XMLHTTPRequest.cpp \
jsb_websocket.cpp
LOCAL_CFLAGS := -DCOCOS2D_JAVASCRIPT

View File

@ -35,7 +35,7 @@
#include "jstypes.h"
#include "jsapi.h"
#include "jsfriendapi.h"
#include "XMLHTTPHelper.h"
#include "jsb_helper.h"
enum MinXmlHttpRequestResponseType {
kRequestResponseTypeString,

View File

@ -0,0 +1,388 @@
/****************************************************************************
Copyright (c) 2013 cocos2d-x.org
Copyright (c) 2013 James Chen
http://www.cocos2d-x.org
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#include "jsb_websocket.h"
#include "cocos2d.h"
#include "WebSocket.h"
#include "spidermonkey_specifics.h"
#include "ScriptingCore.h"
#include "cocos2d_specifics.hpp"
USING_NS_CC_EXT;
/*
[Constructor(in DOMString url, in optional DOMString protocols)]
[Constructor(in DOMString url, in optional DOMString[] protocols)]
interface WebSocket {
readonly attribute DOMString url;
// ready state
const unsigned short CONNECTING = 0;
const unsigned short OPEN = 1;
const unsigned short CLOSING = 2;
const unsigned short CLOSED = 3;
readonly attribute unsigned short readyState;
readonly attribute unsigned long bufferedAmount;
// networking
attribute Function onopen;
attribute Function onmessage;
attribute Function onerror;
attribute Function onclose;
readonly attribute DOMString protocol;
void send(in DOMString data);
void close();
};
WebSocket implements EventTarget;
*/
class JSB_WebSocketDelegate : public WebSocket::Delegate
{
public:
virtual void onOpen(WebSocket* ws)
{
js_proxy_t * p;
JS_GET_PROXY(p, ws);
if (!p) return;
JSContext* cx = ScriptingCore::getInstance()->getGlobalContext();
JSObject* jsobj = JS_NewObject(cx, NULL, NULL, NULL);
jsval vp = c_string_to_jsval(cx, "open");
JS_SetProperty(cx, jsobj, "type", &vp);
jsval args = OBJECT_TO_JSVAL(jsobj);
ScriptingCore::getInstance()->executeFunctionWithOwner(OBJECT_TO_JSVAL(m_pJSDelegate), "onopen", 1, &args);
}
virtual void onMessage(WebSocket* ws, const WebSocket::Data& data)
{
js_proxy_t * p;
JS_GET_PROXY(p, ws);
if (!p) return;
JSContext* cx = ScriptingCore::getInstance()->getGlobalContext();
JSObject* jsobj = JS_NewObject(cx, NULL, NULL, NULL);
jsval vp = c_string_to_jsval(cx, "message");
JS_SetProperty(cx, jsobj, "type", &vp);
jsval args = OBJECT_TO_JSVAL(jsobj);
if (data.isBinary)
{// data is binary
JSObject* buffer = JS_NewArrayBuffer(cx, data.len);
uint8_t* bufdata = JS_GetArrayBufferData(buffer);
memcpy((void*)bufdata, (void*)data.bytes, data.len);
jsval dataVal = OBJECT_TO_JSVAL(buffer);
JS_SetProperty(cx, jsobj, "data", &dataVal);
}
else
{// data is string
jsval dataVal = c_string_to_jsval(cx, data.bytes);
JS_SetProperty(cx, jsobj, "data", &dataVal);
}
ScriptingCore::getInstance()->executeFunctionWithOwner(OBJECT_TO_JSVAL(m_pJSDelegate), "onmessage", 1, &args);
}
virtual void onClose(WebSocket* ws)
{
js_proxy_t * p;
JS_GET_PROXY(p, ws);
if (!p) return;
JSContext* cx = ScriptingCore::getInstance()->getGlobalContext();
JSObject* jsobj = JS_NewObject(cx, NULL, NULL, NULL);
jsval vp = c_string_to_jsval(cx, "close");
JS_SetProperty(cx, jsobj, "type", &vp);
jsval args = OBJECT_TO_JSVAL(jsobj);
ScriptingCore::getInstance()->executeFunctionWithOwner(OBJECT_TO_JSVAL(m_pJSDelegate), "onclose", 1, &args);
js_proxy_t* jsproxy;
JS_GET_NATIVE_PROXY(jsproxy, p->obj);
JS_RemoveObjectRoot(cx, &jsproxy->obj);
JS_REMOVE_PROXY(p, jsproxy);
CC_SAFE_DELETE(ws);
}
virtual void onError(WebSocket* ws, const WebSocket::ErrorCode& error)
{
js_proxy_t * p;
JS_GET_PROXY(p, ws);
if (!p) return;
JSContext* cx = ScriptingCore::getInstance()->getGlobalContext();
JSObject* jsobj = JS_NewObject(cx, NULL, NULL, NULL);
jsval vp = c_string_to_jsval(cx, "error");
JS_SetProperty(cx, jsobj, "type", &vp);
jsval args = OBJECT_TO_JSVAL(jsobj);
ScriptingCore::getInstance()->executeFunctionWithOwner(OBJECT_TO_JSVAL(m_pJSDelegate), "onerror", 1, &args);
}
void setJSDelegate(JSObject* pJSDelegate)
{
m_pJSDelegate = pJSDelegate;
}
private:
JSObject* m_pJSDelegate;
};
JSClass *js_cocos2dx_websocket_class;
JSObject *js_cocos2dx_websocket_prototype;
void js_cocos2dx_WebSocket_finalize(JSFreeOp *fop, JSObject *obj) {
CCLOG("jsbindings: finalizing JS object %p (WebSocket)", obj);
}
JSBool js_cocos2dx_extension_WebSocket_send(JSContext *cx, uint32_t argc, jsval *vp)
{
jsval *argv = JS_ARGV(cx, vp);
JSObject *obj = JS_THIS_OBJECT(cx, vp);
js_proxy_t *proxy; JS_GET_NATIVE_PROXY(proxy, obj);
WebSocket* cobj = (WebSocket *)(proxy ? proxy->ptr : NULL);
JSB_PRECONDITION2( cobj, cx, JS_FALSE, "Invalid Native Object");
if(argc == 1){
do
{
if (JSVAL_IS_STRING(argv[0]))
{
std::string data;
jsval_to_std_string(cx, argv[0], &data);
cobj->send(data);
break;
}
if (argv[0].isObject())
{
uint8_t *bufdata = NULL;
uint32_t len = 0;
JSObject* jsobj = JSVAL_TO_OBJECT(argv[0]);
if (JS_IsArrayBufferObject(jsobj))
{
bufdata = JS_GetArrayBufferData(jsobj);
len = JS_GetArrayBufferByteLength(jsobj);
}
else if (JS_IsArrayBufferViewObject(jsobj))
{
bufdata = (uint8_t*)JS_GetArrayBufferViewData(jsobj);
len = JS_GetArrayBufferViewByteLength(jsobj);
}
if (bufdata && len > 0)
{
cobj->send(bufdata, len);
break;
}
}
JS_ReportError(cx, "data type to be sent is unsupported.");
} while (0);
JS_SET_RVAL(cx, vp, JSVAL_VOID);
return JS_TRUE;
}
JS_ReportError(cx, "wrong number of arguments: %d, was expecting %d", argc, 0);
return JS_TRUE;
}
JSBool js_cocos2dx_extension_WebSocket_close(JSContext *cx, uint32_t argc, jsval *vp){
JSObject *obj = JS_THIS_OBJECT(cx, vp);
js_proxy_t *proxy; JS_GET_NATIVE_PROXY(proxy, obj);
WebSocket* cobj = (WebSocket *)(proxy ? proxy->ptr : NULL);
JSB_PRECONDITION2( cobj, cx, JS_FALSE, "Invalid Native Object");
if(argc == 0){
cobj->close();
JS_SET_RVAL(cx, vp, JSVAL_VOID);
return JS_TRUE;
}
JS_ReportError(cx, "wrong number of arguments: %d, was expecting %d", argc, 0);
return JS_FALSE;
}
JSBool js_cocos2dx_extension_WebSocket_constructor(JSContext *cx, uint32_t argc, jsval *vp)
{
jsval *argv = JS_ARGV(cx, vp);
if (argc == 1 || argc == 2)
{
std::string url;
do {
JSBool ok = jsval_to_std_string(cx, argv[0], &url);
JSB_PRECONDITION2( ok, cx, JS_FALSE, "Error processing arguments");
} while (0);
JSObject *obj = JS_NewObject(cx, js_cocos2dx_websocket_class, js_cocos2dx_websocket_prototype, NULL);
cocos2d::extension::WebSocket* cobj = new cocos2d::extension::WebSocket();
JSB_WebSocketDelegate* delegate = new JSB_WebSocketDelegate();
delegate->setJSDelegate(obj);
if (argc == 2)
{
std::vector<std::string> protocols;
if (JSVAL_IS_STRING(argv[1]))
{
std::string protocol;
do {
JSBool ok = jsval_to_std_string(cx, argv[1], &protocol);
JSB_PRECONDITION2( ok, cx, JS_FALSE, "Error processing arguments");
} while (0);
protocols.push_back(protocol);
}
else if (argv[1].isObject())
{
JSBool ok = JS_TRUE;
JSObject* arg2 = JSVAL_TO_OBJECT(argv[1]);
JSB_PRECONDITION(JS_IsArrayObject( cx, arg2 ), "Object must be an array");
uint32_t len = 0;
JS_GetArrayLength(cx, arg2, &len);
for( uint32_t i=0; i< len;i++ )
{
jsval valarg;
JS_GetElement(cx, arg2, i, &valarg);
std::string protocol;
do {
ok = jsval_to_std_string(cx, valarg, &protocol);
JSB_PRECONDITION2( ok, cx, JS_FALSE, "Error processing arguments");
} while (0);
protocols.push_back(protocol);
}
}
cobj->init(*delegate, url, &protocols);
}
else
{
cobj->init(*delegate, url);
}
JS_DefineProperty(cx, obj, "URL", argv[0]
, NULL, NULL, JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_READONLY);
//protocol not support yet (always return "")
JS_DefineProperty(cx, obj, "protocol", c_string_to_jsval(cx, "")
, NULL, NULL, JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_READONLY);
// link the native object with the javascript object
js_proxy_t *p;
JS_NEW_PROXY(p, cobj, obj);
JS_AddNamedObjectRoot(cx, &p->obj, "WebSocket");
JS_SET_RVAL(cx, vp, OBJECT_TO_JSVAL(obj));
return JS_TRUE;
}
JS_ReportError(cx, "wrong number of arguments: %d, was expecting %d", argc, 0);
return JS_FALSE;
}
static JSBool js_cocos2dx_extension_WebSocket_get_readyState(JSContext *cx, JSHandleObject obj, JSHandleId id, JSMutableHandleValue vp)
{
JSObject* jsobj = obj.get();
js_proxy_t *proxy; JS_GET_NATIVE_PROXY(proxy, jsobj);
WebSocket* cobj = (WebSocket *)(proxy ? proxy->ptr : NULL);
JSB_PRECONDITION2( cobj, cx, JS_FALSE, "Invalid Native Object");
if (cobj) {
vp.set(INT_TO_JSVAL((int)cobj->getReadyState()));
return JS_TRUE;
} else {
JS_ReportError(cx, "Error: WebSocket instance is invalid.");
return JS_FALSE;
}
}
void register_jsb_websocket(JSContext *cx, JSObject *global) {
js_cocos2dx_websocket_class = (JSClass *)calloc(1, sizeof(JSClass));
js_cocos2dx_websocket_class->name = "WebSocket";
js_cocos2dx_websocket_class->addProperty = JS_PropertyStub;
js_cocos2dx_websocket_class->delProperty = JS_PropertyStub;
js_cocos2dx_websocket_class->getProperty = JS_PropertyStub;
js_cocos2dx_websocket_class->setProperty = JS_StrictPropertyStub;
js_cocos2dx_websocket_class->enumerate = JS_EnumerateStub;
js_cocos2dx_websocket_class->resolve = JS_ResolveStub;
js_cocos2dx_websocket_class->convert = JS_ConvertStub;
js_cocos2dx_websocket_class->finalize = js_cocos2dx_WebSocket_finalize;
js_cocos2dx_websocket_class->flags = JSCLASS_HAS_RESERVED_SLOTS(2);
static JSPropertySpec properties[] = {
{"readyState", 0, JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED, JSOP_WRAPPER(js_cocos2dx_extension_WebSocket_get_readyState), NULL},
{0, 0, 0, 0, 0}
};
static JSFunctionSpec funcs[] = {
JS_FN("send",js_cocos2dx_extension_WebSocket_send, 1, JSPROP_PERMANENT | JSPROP_ENUMERATE),
JS_FN("close",js_cocos2dx_extension_WebSocket_close, 0, JSPROP_PERMANENT | JSPROP_ENUMERATE),
JS_FS_END
};
static JSFunctionSpec st_funcs[] = {
JS_FS_END
};
js_cocos2dx_websocket_prototype = JS_InitClass(
cx, global,
NULL,
js_cocos2dx_websocket_class,
js_cocos2dx_extension_WebSocket_constructor, 0, // constructor
properties,
funcs,
NULL, // no static properties
st_funcs);
JSObject* jsclassObj = JSVAL_TO_OBJECT(anonEvaluate(cx, global, "(function () { return WebSocket; })()"));
JS_DefineProperty(cx, jsclassObj, "CONNECTING", INT_TO_JSVAL((int)WebSocket::kStateConnecting)
, NULL, NULL, JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_READONLY);
JS_DefineProperty(cx, jsclassObj, "OPEN", INT_TO_JSVAL((int)WebSocket::kStateOpen)
, NULL, NULL, JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_READONLY);
JS_DefineProperty(cx, jsclassObj, "CLOSING", INT_TO_JSVAL((int)WebSocket::kStateClosing)
, NULL, NULL, JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_READONLY);
JS_DefineProperty(cx, jsclassObj, "CLOSED", INT_TO_JSVAL((int)WebSocket::kStateClosed)
, NULL, NULL, JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_READONLY);
// make the class enumerable in the registered namespace
JSBool found;
JS_SetPropertyAttributes(cx, global, "WebSocket", JSPROP_ENUMERATE | JSPROP_READONLY, &found);
}

View File

@ -0,0 +1,34 @@
/****************************************************************************
Copyright (c) 2013 cocos2d-x.org
Copyright (c) 2013 James Chen
http://www.cocos2d-x.org
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#ifndef __jsb_websocket__
#define __jsb_websocket__
#include "jsapi.h"
#include "jsfriendapi.h"
void register_jsb_websocket(JSContext* cx, JSObject* global);
#endif /* defined(__jsb_websocket__) */

View File

@ -19,6 +19,7 @@
<ClCompile Include="..\jsb_opengl_functions.cpp" />
<ClCompile Include="..\jsb_opengl_manual.cpp" />
<ClCompile Include="..\jsb_opengl_registration.cpp" />
<ClCompile Include="..\jsb_websocket.cpp" />
<ClCompile Include="..\js_bindings_ccbreader.cpp" />
<ClCompile Include="..\js_bindings_chipmunk_auto_classes.cpp" />
<ClCompile Include="..\js_bindings_chipmunk_functions.cpp" />
@ -38,9 +39,11 @@
<ClInclude Include="..\generated\jsb_cocos2dx_auto.hpp" />
<ClInclude Include="..\generated\jsb_cocos2dx_extension_auto.hpp" />
<ClInclude Include="..\jsb_cocos2dx_extension_manual.h" />
<ClInclude Include="..\jsb_helper.h" />
<ClInclude Include="..\jsb_opengl_functions.h" />
<ClInclude Include="..\jsb_opengl_manual.h" />
<ClInclude Include="..\jsb_opengl_registration.h" />
<ClInclude Include="..\jsb_websocket.h" />
<ClInclude Include="..\js_bindings_ccbreader.h" />
<ClInclude Include="..\js_bindings_chipmunk_auto_classes.h" />
<ClInclude Include="..\js_bindings_chipmunk_auto_classes_registration.h" />
@ -57,7 +60,6 @@
<ClInclude Include="..\js_manual_conversions.h" />
<ClInclude Include="..\ScriptingCore.h" />
<ClInclude Include="..\spidermonkey_specifics.h" />
<ClInclude Include="..\XMLHTTPHelper.h" />
<ClInclude Include="..\XMLHTTPRequest.h" />
</ItemGroup>
<ItemGroup>
@ -125,7 +127,7 @@
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_WINDOWS;_DEBUG;_LIB;DEBUG;COCOS2D_DEBUG=1;XP_WIN;JS_HAVE___INTN;JS_INTPTR_TYPE=int;COCOS2D_JAVASCRIPT=1;CC_ENABLE_CHIPMUNK_INTEGRATION=1;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>$(ProjectDir)..\..\..\..\cocos2dx;$(ProjectDir)..\..\..\..\cocos2dx\include;$(ProjectDir)..\..\..\..\cocos2dx\kazmath\include;$(ProjectDir)..\..\..\..\cocos2dx\platform\win32;$(ProjectDir)..\..\..\..\cocos2dx\platform\third_party\win32;$(ProjectDir)..\..\..\..\cocos2dx\platform\third_party\win32\pthread;$(ProjectDir)..\..\..\..\cocos2dx\platform\third_party\win32\OGLES;$(ProjectDir)..\..\..\..\CocosDenshion\include;$(ProjectDir)..;$(ProjectDir)..\..\spidermonkey-win32\include;$(ProjectDir)..\..\..\..\external\chipmunk\include\chipmunk;$(ProjectDir)..\..\..\..\extensions;$(ProjectDir)..\..\..\..\extensions\LocalStorage;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>$(ProjectDir)..\..\..\..\cocos2dx;$(ProjectDir)..\..\..\..\cocos2dx\include;$(ProjectDir)..\..\..\..\cocos2dx\kazmath\include;$(ProjectDir)..\..\..\..\cocos2dx\platform\win32;$(ProjectDir)..\..\..\..\cocos2dx\platform\third_party\win32;$(ProjectDir)..\..\..\..\cocos2dx\platform\third_party\win32\pthread;$(ProjectDir)..\..\..\..\cocos2dx\platform\third_party\win32\OGLES;$(ProjectDir)..\..\..\..\CocosDenshion\include;$(ProjectDir)..;$(ProjectDir)..\..\spidermonkey-win32\include;$(ProjectDir)..\..\..\..\external\chipmunk\include\chipmunk;$(ProjectDir)..\..\..\..\external\libwebsockets\win32\include;$(ProjectDir)..\..\..\..\extensions;$(ProjectDir)..\..\..\..\extensions\LocalStorage;$(ProjectDir)..\..\..\..\extensions\network;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<DisableSpecificWarnings>4068;4101;4800;4251;4996;4244;%(DisableSpecificWarnings)</DisableSpecificWarnings>
</ClCompile>
<Link>
@ -146,7 +148,7 @@ xcopy /Y /Q "$(ProjectDir)..\..\..\..\external\sqlite3\libraries\win32\*.*" "$(O
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;_WINDOWS;NDEBUG;_LIB;XP_WIN;JS_HAVE___INTN;JS_INTPTR_TYPE=int;COCOS2D_JAVASCRIPT=1;CC_ENABLE_CHIPMUNK_INTEGRATION=1;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>$(ProjectDir)..\..\..\..\cocos2dx;$(ProjectDir)..\..\..\..\cocos2dx\include;$(ProjectDir)..\..\..\..\cocos2dx\kazmath\include;$(ProjectDir)..\..\..\..\cocos2dx\platform\win32;$(ProjectDir)..\..\..\..\cocos2dx\platform\third_party\win32;$(ProjectDir)..\..\..\..\cocos2dx\platform\third_party\win32\pthread;$(ProjectDir)..\..\..\..\cocos2dx\platform\third_party\win32\OGLES;$(ProjectDir)..\..\..\..\CocosDenshion\include;$(ProjectDir)..;$(ProjectDir)..\..\spidermonkey-win32\include;$(ProjectDir)..\..\..\..\external\chipmunk\include\chipmunk;$(ProjectDir)..\..\..\..\extensions;$(ProjectDir)..\..\..\..\extensions\LocalStorage;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>$(ProjectDir)..\..\..\..\cocos2dx;$(ProjectDir)..\..\..\..\cocos2dx\include;$(ProjectDir)..\..\..\..\cocos2dx\kazmath\include;$(ProjectDir)..\..\..\..\cocos2dx\platform\win32;$(ProjectDir)..\..\..\..\cocos2dx\platform\third_party\win32;$(ProjectDir)..\..\..\..\cocos2dx\platform\third_party\win32\pthread;$(ProjectDir)..\..\..\..\cocos2dx\platform\third_party\win32\OGLES;$(ProjectDir)..\..\..\..\CocosDenshion\include;$(ProjectDir)..;$(ProjectDir)..\..\spidermonkey-win32\include;$(ProjectDir)..\..\..\..\external\chipmunk\include\chipmunk;$(ProjectDir)..\..\..\..\external\libwebsockets\win32\include;$(ProjectDir)..\..\..\..\extensions;$(ProjectDir)..\..\..\..\extensions\LocalStorage;$(ProjectDir)..\..\..\..\extensions\network;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<DisableSpecificWarnings>4068;4101;4800;4251;4996;4244;%(DisableSpecificWarnings)</DisableSpecificWarnings>
</ClCompile>
<Link>

View File

@ -74,6 +74,9 @@
<ClCompile Include="..\XMLHTTPRequest.cpp">
<Filter>manual</Filter>
</ClCompile>
<ClCompile Include="..\jsb_websocket.cpp">
<Filter>manual</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\cocos2d_specifics.hpp">
@ -151,7 +154,10 @@
<ClInclude Include="..\XMLHTTPRequest.h">
<Filter>manual</Filter>
</ClInclude>
<ClInclude Include="..\XMLHTTPHelper.h">
<ClInclude Include="..\jsb_websocket.h">
<Filter>manual</Filter>
</ClInclude>
<ClInclude Include="..\jsb_helper.h">
<Filter>manual</Filter>
</ClInclude>
</ItemGroup>