FFL_WebSocketServer.cpp 7.8 KB
Newer Older
L
libb 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254
/*
*  This file is part of FFL project.
*
*  The MIT License (MIT)
*  Copyright (C) 2017-2018 zhufeifei All rights reserved.
*
*  FFL_WebSocketServer.cpp
*  Created by zhufeifei(34008081@qq.com) on 2019/02/24
*  https://github.com/zhenfei2016/FFLv2-lib.git
*
*  websocket服务器
*  
*  协议解析
*  https://blog.csdn.net/vsrfind/article/details/79268411
*  https://tools.ietf.org/html/rfc6455
*/

#include <net/websocket/FFL_WebSocketServer.hpp>
#include <net/http/FFL_HttpUrl.hpp>
#include <net/http/FFL_HttpRequest.hpp>
#include <net/FFL_TcpClient.hpp>
#include <net/FFL_TcpServer.hpp>
#include <net/http/FFL_HttpClient.hpp>
#include <net/websocket/FFL_WebSocketClient.hpp>
#include <list>
#include "FFL_WebSocketHandshark.hpp"
#include "FFL_WebSocketFrame.hpp"
#include "FFL_WebSocket.hpp"
namespace FFL {
	#define  kMaxFrameSize  4096
	class WebSocketAcceptClient : public RefBase {
	public:
		WebSocketAcceptClient(TcpClient* client):mClient(client), mStream(client){
			mWebSocket = new WebSocket(client,&mStream,false,NULL);
		}
		~WebSocketAcceptClient(){
			FFL_SafeFree(mWebSocket);
         }
		//
		//  接收一帧数据
		//  buffer: 缓冲区 , 
		//  bufferSize:这个输入缓冲区的大小。 当成功接收数据的情况下返回接收的数据大小
		//
		bool recvFrame(uint8_t* data, uint32_t requstSize, uint32_t*  readed) {
			WebsocketFrame frame;
			if (!mWebSocket->recvFrameHead(frame)) {
				return false;
			}
			
			if (frame.mOpcode == WebsocketFrame::OPCODE_BYE) {
				mWebSocket->sendBye();
				return false;
			}

			if (frame.mOpcode == WebsocketFrame::OPCODE_PING) {
				mWebSocket->sendPong();
				return true;
			}			
			
			if (!frame.readData(&mStream, data,(uint32_t*) readed)) {
				return false;
			}

			return true;
		}

		bool sendFrame(const uint8_t* data, uint32_t len) {
			return mWebSocket->sendFrame(WebsocketFrame::OPCODE_TEXT,data, len);
		}
	private:
		TcpClient* mClient;
		NetStreamReader mStream;
		WebSocket* mWebSocket;
	};

	//
	//  具体服务器实现
	//
	class WebSocketServerImpl :public TcpServer::Callback{
		friend class WebSocketServer;
		public:
			WebSocketServerImpl(const char* ip, int32_t port, WebSocketServer::Callback* callback);
			virtual ~WebSocketServerImpl();
	    protected:		
			//
			//  调用。start,stop会触发onStart,onStop的执行
			//  onStart :表示准备开始了 ,可以做一些初始化工作
			//  onStop :表示准备停止了 ,可以做停止前的准备,想置一下信号让eventloop别卡住啊 
			//  在这些函数中,不要再调用自己的函数,例如:start,stop, isStarted等
			//
			FFL_INLINE bool onStart();
			FFL_INLINE void onStop();
			//
			//   阻塞的线程中执行的eventloop,返回是否继续进行eventLoop
			//   waitTime:输出参数,下一次执行eventLoop等待的时长
			//   true  : 继续进行下一次的eventLoop
			//   false : 不需要继续执行eventloop
			//
			FFL_INLINE bool eventLoop(int32_t* waitTime);
		private:	
			// class TcpServer::Callback
			//
			//  aliveTimeUs:保活时长,如果超过这么长时间还没有数据则干掉这个client
			//              <0 一直存活, 
			//
			virtual bool onClientCreate(TcpClient* client, int64_t* aliveTimeUs);
			virtual void onClientDestroy(TcpClient* client, TcpServer::Callback::FD_OPTMODE reason);
			virtual TcpServer::Callback::FD_OPTMODE onClientReceived(TcpClient* client);
	    private:
			TcpServer* mTcpServer;	
			WebSocketServer::Callback* mCallback;
	};

	WebSocketServerImpl::WebSocketServerImpl(const char* ip, int32_t port, WebSocketServer::Callback* callback):
		mCallback(callback){
		mTcpServer = new TcpServer(ip,port, this);
	}
	WebSocketServerImpl::~WebSocketServerImpl(){
		FFL_SafeFree(mTcpServer);		
	}


	//
	//  内部保存的一条http连接上,的一下相关信息
	//
	class WebsocketContext {
	public:
		WebsocketContext(TcpClient* client);
		~WebsocketContext();

		TcpClient* mTcpClient;
		FFL::sp<WebSocketAcceptClient> mWebsocket;

		//
		//  是否已经握手成功了
		//
		bool mHandshake;
	};
	WebsocketContext::WebsocketContext(TcpClient* client):mTcpClient(client){
		mWebsocket = new WebSocketAcceptClient(client);
		mHandshake = false;
	}
	WebsocketContext::~WebsocketContext() {				
		mTcpClient = NULL;
	}
	//
	//  一条http连接开始建立
	//
	bool WebSocketServerImpl::onClientCreate(TcpClient* client, int64_t* aliveTimeUs) {
		WebsocketContext* contex = new WebsocketContext(client);
		client->setUserdata(contex);
		return true;
	}
	void WebSocketServerImpl::onClientDestroy(TcpClient* client, TcpServer::Callback::FD_OPTMODE reason) {
		WebsocketContext* contex = (WebsocketContext*)client->getUserdata();
		client->setUserdata(NULL);
		FFL_SafeFree(contex);
	}
	//
	//  client上有数据可以读了
	//
	TcpServer::Callback::FD_OPTMODE WebSocketServerImpl::onClientReceived(TcpClient* client) {
		WebsocketContext* contex = (WebsocketContext*)client->getUserdata();
		if (!contex->mHandshake) {
			//
			//  握手请求
			//
			sp<HttpClient> httpClient = new HttpClient(client);
			FFL::sp<HttpRequest> request = httpClient->readRequest();
			if (request.isEmpty() || 
				!WebSocket_isHandsharkRequest(request.get())) {
				return TcpServer::Callback::FD_DESTROY;
			}					

			String key;
			if (!WebSocket_getSecWebSocketkey(request.get(), key)) {
				return TcpServer::Callback::FD_DESTROY;
			}
						
			FFL::sp<WSHandsharkResponse> response =
				new WSHandsharkResponse(httpClient, key);
			response->send();			
			contex->mHandshake = true;
			return TcpServer::Callback::FD_CONTINUE;
		}
		//
		//  读数据
		//
		uint8_t buffer[4095] = {};
		uint32_t readedSize = 4095;
		if (!contex->mWebsocket->recvFrame(buffer,4096, &readedSize)) {
			return TcpServer::Callback::FD_DESTROY;
		}
		
		//if (readedSize > 0) {
		//	//
		//	//  回复  echo模式
		//	contex->mWebsocket->sendFrame(buffer, readedSize);
		//}

		return TcpServer::Callback::FD_CONTINUE;		
	}
	
	//
	//  调用。start,stop会触发onStart,onStop的执行
	//  onStart :表示准备开始了 ,可以做一些初始化工作
	//  onStop :表示准备停止了 ,可以做停止前的准备,想置一下信号让eventloop别卡住啊 
	//  在这些函数中,不要再调用自己的函数,例如:start,stop, isStarted等
	//
	FFL_INLINE bool WebSocketServerImpl::onStart() {
		mTcpServer->start(NULL);
		return true;
	}
	FFL_INLINE void WebSocketServerImpl::onStop() {
		mTcpServer->stop();
	}	
	//
	//   阻塞的线程中执行的eventloop,返回是否继续进行eventLoop
	//   waitTime:输出参数,下一次执行eventLoop等待的时长
	//   true  : 继续进行下一次的eventLoop
	//   false : 不需要继续执行eventloop
	//
	FFL_INLINE bool WebSocketServerImpl::eventLoop(int32_t* waitTime) {
		return mTcpServer->eventLoop(waitTime);
	}
	////////////////////////////////////////////////////////////////////////////////////////////////////////
	WebSocketServer::WebSocketServer(const char* ip, int32_t port, Callback* callback) {
		mImpl = new WebSocketServerImpl(ip, port,callback);
	}
	WebSocketServer::~WebSocketServer() {
		FFL_SafeFree(mImpl);
	}	
	//
	//  调用。start,stop会触发onStart,onStop的执行
	//  onStart :表示准备开始了 ,可以做一些初始化工作
	//  onStop :表示准备停止了 ,可以做停止前的准备,想置一下信号让eventloop别卡住啊 
	//  在这些函数中,不要再调用自己的函数,例如:start,stop, isStarted等
	//
	bool WebSocketServer::onStart() {
		return mImpl->onStart();
	}
	void WebSocketServer::onStop() {
		mImpl->onStop();
	}	
	//
	//   阻塞的线程中执行的eventloop,返回是否继续进行eventLoop
	//   waitTime:输出参数,下一次执行eventLoop等待的时长
	//   true  : 继续进行下一次的eventLoop
	//   false : 不需要继续执行eventloop
	//
	bool WebSocketServer::eventLoop(int32_t* waitTime) {
		return mImpl->eventLoop(waitTime);
	}
}