web socket RFC6455 frame 打包、解包
#ifndef __APP_WEBSOCKET_FRAME_H__
#define __APP_WEBSOCKET_FRAME_H__
#include "memory.hpp"
class buffer;
struct websocket_frame
{
websocket_frame();
~websocket_frame();
static const unsigned int fix_min_len = 2;
static const unsigned int fix_masking_len = 4;
static const unsigned int fix_126_len = 2;
static const unsigned int fix_127_len = 8;
bool fin;
bool rsv1;
bool rsv2;
bool rsv3;
unsigned char opcode;
bool mask;
unsigned char payload_len ;
unsigned short payload_126_len;
unsigned long long payload_127_len;
unsigned char masking_key[4];
shared_ptr<buffer> payload;
unsigned int get_head_len() const ;
unsigned int get_total_len() const ;
unsigned int get_payload_len() const ;
//解包
int unpakcage( const shared_ptr<buffer> & buf );
//打包
unsigned int package_size() ;
shared_ptr<buffer> package() ;
protected:
void set_masking_key( unsigned char * data, int offset);
void get_masking_key( unsigned char * data, int offset);
};
#endif
#include "websocket_frame.hpp"
#include "buffer_pool.hpp"
#include <cstring>
#include <glog/logging.h>
#include <cstdlib>
websocket_frame::websocket_frame():fin(false)
,rsv1(false),rsv2(false),rsv3(false),mask(false),opcode(0)
,payload_len(0),payload_126_len(0),payload_127_len(0)
{
int rand_var = rand();
masking_key[0] = (rand_var & 0xff000000)>>24;
masking_key[1] = (rand_var & 0x00ff0000) >> 16;
masking_key[2] = ( rand_var & 0x0000ff00) >> 8;
masking_key[3] = rand_var & 0x000000ff;
}
websocket_frame::~websocket_frame(){
if( payload ){
recycle_buffer(payload);
}
}
void websocket_frame::set_masking_key( unsigned char * data, int offset){
masking_key[0] = data[0+offset];
masking_key[1] = data[1+offset];
masking_key[2] = data[2+offset];
masking_key[3] = data[3+offset];
}
void websocket_frame:: get_masking_key( unsigned char * data, int offset){
data[0+offset] = masking_key[0];
data[1+offset] = masking_key[1] ;
data[2+offset] = masking_key[2];
data[3+offset] = masking_key[3] ;
}
unsigned int websocket_frame::get_head_len() const {
return get_total_len() - get_payload_len();
}
unsigned int websocket_frame::get_total_len() const {
if( mask ){
if( payload_len < 126 ){
return payload_len + fix_min_len + fix_masking_len;
}else if( payload_len == 126 ){
return payload_126_len + fix_min_len + fix_masking_len + fix_126_len;
}else {
return payload_127_len +fix_min_len + fix_masking_len + fix_127_len;
}
}else{
if( payload_len < 126 ){
return payload_len + fix_min_len;
}else if( payload_len == 126 ){
return payload_126_len + fix_min_len + fix_126_len;
}else {
return payload_127_len + fix_min_len + fix_127_len;
}
}
}
unsigned int websocket_frame::get_payload_len() const {
if( payload_len < 126 ){
return payload_len;
}else if( payload_len == 126 ){
return payload_126_len;
}else {
return payload_127_len;
}
}
int websocket_frame::unpakcage( const shared_ptr<buffer> & buf ){
if( buf->length() == 0 ){
return 2;
}
unsigned char * data = buf->data();
fin = data[0] & 0x80;
rsv1 = data[0] & (0x40 );
rsv2 = data[0] & ( 0x20);
rsv3 = data[0] & ( 0x10);
opcode = (data[0] & 0x0f) ;
mask = data[1] & 0x80;
payload_len = data[1] & 0x7f;
if( payload_len < 126 ){
if( buf->length() < get_total_len() ){
return get_total_len() - buf->length();
}
payload = get_buffer( get_payload_len());
unsigned char * pdata = payload->data();
if( mask ){
set_masking_key(data,2);
int i;
for( i = 0 ; i < payload_len; i ++ ){
pdata[i] = data[6+i] ^ masking_key[i%4];
}
}else{
memcpy(pdata, data+2, get_payload_len());
}
payload->size(get_payload_len());
}else if( payload_len == 126 ){
if( buf->length() < 4 ){
return 4 - buf->length();
}
payload_126_len = (data[2] << 8 )| data[3];
if( buf->length() < get_total_len() ){
return get_total_len() - buf->length();
}
payload = get_buffer( get_payload_len());
unsigned char * pdata = payload->data();
if( mask ){
set_masking_key(data,4);
int i;
for( i = 0 ; i < payload_126_len; i ++ ){
pdata[i] = data[8+i] ^ masking_key[i%4];
}
}else{
memcpy(pdata, data+4, get_payload_len());
}
payload->size(get_payload_len());
}else{ // 127
LOG(FATAL)<<"un support big frame for websocket.";
}
return 0;
}
unsigned int websocket_frame::package_size() {
if( payload->length() < 126 ){
payload_len = payload->length();
}else if( payload->length() < 0xffff ){
payload_len = 126;
payload_126_len = payload->length();
}else{
payload_len = 127;
payload_127_len = payload->length();
}
return get_total_len();
}
shared_ptr<buffer> websocket_frame::package() {
shared_ptr<buffer> buf = get_buffer( package_size());
buf->size(package_size());
unsigned char * data = buf->data();
data[0] = 0;
if( fin ){
data[0] |= 0x80;
}
if( rsv1 ){
data[0] |= 0x40;
}
if( rsv2 ){
data[0] |= 0x20;
}
if( rsv3 ) {
data[0] |= 0x10;
}
data[0] |= (opcode & 0x0f);
data[1] = 0;
if( mask ){
data[1] |= 0x80;
}
data[1] |=( payload_len & 0x7f);
unsigned char * pdata = payload->data();
if( payload_len < 126 ){
if( mask ){
//get_masking_key(data,2);
data[2] = masking_key[0];
data[3] = masking_key[1];
data[4] = masking_key[2];
data[5] = masking_key[3];
int i = 0;
for( i = 0 ; i < payload_len; i ++ ){
data[6+i] = pdata[i] ^ masking_key[i%4];
}
}else{
memcpy(data+2, pdata,payload_len);
}
}else if( payload_len == 126 ){
data[2] =(unsigned char)( (payload_126_len & 0xff00) >> 8);
data[3] =(unsigned char) (payload_126_len & 0x00ff);
if( mask ){
data[4] = masking_key[0];
data[5] = masking_key[1];
data[6] = masking_key[2];
data[7] = masking_key[3];
int i = 0;
for( i = 0 ; i < payload_126_len; i ++ ){
data[8+i] = pdata[i] ^ masking_key[i%4];
}
}else{
memcpy(data+4, pdata,payload_126_len);
}
}else if( payload_len == 127 ){
LOG(FATAL)<<"no support 127 web socket frame.";
}
return buf;
}
重点在unpakcage方法,该方法在解包成功时,返回0,失败时。返回还须要多少字节才干够解析一个完整的包。
另外临时没有计算payload_len=127情况下。主要是大部分环境下不须要用到那么大。
解包成功后。get_head_len、get_total_len、get_payload_len调用时,都能够返回正确的数据,假设unpackage返回大于0时,调用关于len的函数是属于非法的。
。
web socket RFC6455 frame 打包、解包的更多相关文章
- 基于RTP的H264视频数据打包解包类
from:http://blog.csdn.net/dengzikun/article/details/5807694 最近考虑使用RTP替换原有的高清视频传输协议,遂上网查找有关H264视频RTP打 ...
- (转)基于RTP的H264视频数据打包解包类
最近考虑使用RTP替换原有的高清视频传输协议,遂上网查找有关H264视频RTP打包.解包的文档和代码.功夫不负有心人,找到不少有价值的文档和代码.参考这些资料,写了H264 RTP打包类.解包类,实现 ...
- Mtk Android 打包解包*.img
打包/解包 boot.img, system.img, userdata.img, or recovery.img [DESCRIPTION] MTK codebase编译出来的image必须使用MT ...
- Java之集合初探(二)Iterator(迭代器),collections,打包/解包(装箱拆箱),泛型(Generic),comparable接口
Iterator(迭代器) 所有实现了Collection接口的容器都有一个iterator方法, 用来返回一个实现了Iterator接口的对象 Iterator对象称作迭代器, 用来方便的实现对容器 ...
- 【Unity】AssetBundle的使用——打包/解包
最近参考了各位大神的资源,初步学习了Unity的资源管理模式,包括在编辑器管理(使用AssetDatabase)和在运行时管理(使用Resources和AssetBundle).在此简单总结运行时用A ...
- xpack文件打包解包代码库
Github ###概述 xpack是一个文件资源打包工具及类库,可以对多文件进行打包解包. 其使用文件名的hash作为索引,建立hash索引表以加速文件查找. ###特性 支持hashid自动解冲突 ...
- Ruby中星号打包解包操作
Ruby中可以使用一个星号*和两个星号**完成一些打包.解包操作,它们称为splat操作符: 一个星号:以数组为依据进行打包解包(参考文章) 两个星号:以hash为依据进行打包解包(参考文章) 两个星 ...
- 07.进程管理+作业控制+文件查找与压缩+文件压缩与打包+tar打包解包+NFS
进程管理 程序放在磁盘上叫文件,把它复制到内存,并在cpu运行,就叫进程, 进程多少也反映当前运行程序的多少 进程在系统中会为每个进程生成一个进程号,在所有的进程中有一个特殊进程即init进程, 它是 ...
- linux 配置网卡、远程拷贝文件、建立软硬链接、打包/解包、压缩/解压缩、包操作、yum配置使用、root密码忘记
目录 一.配置网卡 二.xshell连接 三.远程拷贝文件 四.建立软硬连接 五.打包/解包和压缩/解压缩 六.包操作 七.配置yum源 配置yum源 配置阿里云源 常用命令 yum其他命令 八.重置 ...
随机推荐
- netty源码解解析(4.0)-13 Channel NIO实现: 关闭和清理
Channel提供了3个方法用来实现关闭清理功能:disconnect,close,deregister.本章重点分析这个3个方法的功能的NIO实现. disconnect实现: 断开连接 disco ...
- netty源码解解析(4.0)-8 ChannelPipeline的设计
io.netty.channel.ChannelPipeline 设计原理 上图中,为了更直观地展示事件处理顺序, 故意有规律地放置两种handler的顺序,实际上ChannelInboundHa ...
- [译]WebAPI下的如何实现参数绑定
本文将概述在WebAPI方式下将如何将参数绑定到一个action方法,包括参数是如何被读取,一系列规则决定特定环境采用的那种绑定方式,文章最后将给出一些实际的例子. Parameter binding ...
- C#服务端判断客户端socket是否已断开的方法
刚开始,用Socket类的Connected属性来实现,却发现行不通,connected只表示 是在上次 还是 操作时连接到远程主机.如果在这之后[连接的另一方]断开了,它还一直返回true, 除非 ...
- JavaScript基础要点
一.值和类型及运算 JavaScript中的六种基本值类型 数字(number).字符串(string).布尔值(boolean).对象(object).函数(function).未定义类型(unde ...
- sql server: left join 重复数据
---涂聚文 2017-9-28 SELECT VipExamMailProjectId,VipExamMailStaffID FROM VipExamMailRecord WHERE VipExam ...
- HTML-CSS写抽屉网的置顶区域
1.在pycharm的已有工程中新建一个html文件. 2.在<body></body>标签内部写入要内容: <div class='head-box' > < ...
- MySQL安装的挫折之路
由于对MySQL卸载的不干净,mysql 的MySQL Connector Net/xxx无法卸载,后期重装无法成功.所以只能采用zip 安装https://www.cnblogs.com/Micha ...
- CSS效果:CSS实用技巧制作三角形以及箭头效果
实现如图所示的三角形图标: html代码如下: <div class="arrow-up"></div> <div class="arrow ...
- React中props
今天让我们开启新的篇章好吧,来搞一搞React,以下所有操作都是我个人的一些理解,如果有错吴还请指出,想要看更全的可以去React官网可能一下子好吧 昨天按摩没到位,导致今天身体不太行,撸码千万别苦了 ...