Skip to content
Snippets Groups Projects
Commit 9b48221e authored by Elemer Lelik's avatar Elemer Lelik
Browse files

Initial contribution

parent d11df254
No related branches found
No related tags found
No related merge requests found
# titan.ProtocolModules.WebSocket
Main project page:
https://projects.eclipse.org/projects/tools.titan
The source code of the TTCN-3 compiler and executor:
https://github.com/eclipse/titan.core
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (c) 2015 Ericsson
All rights reserved. This program and the accompanying materials
are made available under the terms of the Eclipse Public License v1.0
which accompanies this distribution, and is available at
http://www.eclipse.org/legal/epl-v10.html
File: WebSocket_CNL113782.tpd
Description: tpd project file
Rev: R2A
Prodnr: CNL 113 782
-->
<TITAN_Project_File_Information version="1.0">
<ProjectName>WebSocket_CNL113782</ProjectName>
<Files>
<FileResource projectRelativePath="WebSocket_EncDec.cc" relativeURI="src/WebSocket_EncDec.cc"/>
<FileResource projectRelativePath="WebSocket_Types.ttcn" relativeURI="src/WebSocket_Types.ttcn"/>
</Files>
<ActiveConfiguration>Default</ActiveConfiguration>
<Configurations>
<Configuration name="Default">
<ProjectProperties>
<MakefileSettings>
<generateInternalMakefile>true</generateInternalMakefile>
<GNUMake>true</GNUMake>
<incrementalDependencyRefresh>true</incrementalDependencyRefresh>
<targetExecutable>bin/WebSocket_CNL113782</targetExecutable>
</MakefileSettings>
<LocalBuildSettings>
<workingDirectory>bin</workingDirectory>
</LocalBuildSettings>
<NamingCoventions>
<enableProjectSpecificSettings>true</enableProjectSpecificSettings>
<externalFunction>f_.*</externalFunction>
</NamingCoventions>
</ProjectProperties>
</Configuration>
</Configurations>
</TITAN_Project_File_Information>
File added
File added
<!--
/******************************************************************************
* Copyright (c) 2005, 2015 Ericsson AB
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Gabor Szalai
******************************************************************************/
-->
<!DOCTYPE TITAN_GUI_FileGroup_file>
<FileGroup TITAN_version="3.1.pl0" >
<File_Group name="WebSocket_CNL113782" >
<File path="WebSocket_EncDec.cc" />
<File path="WebSocket_Types.ttcn" />
</File_Group>
</FileGroup>
/******************************************************************************
* Copyright (c) 2005, 2015 Ericsson AB
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Gabor Szalai
******************************************************************************/
//
// File: WebSocket_EncDec.cc
// Prodnr: CNL 113 782
// Rev: R2A
#include "WebSocket_Types.hh"
#include <stdlib.h>
#include <time.h>
#include <sys/types.h>
static const unsigned char zero_data[]={0,0,0,0};
static const OCTETSTRING zero_oct=OCTETSTRING(4,&zero_data[0]);
namespace WebSocket__Types {
void do_mask(const unsigned char* key, const unsigned char* source,
unsigned char* target, size_t size){
int key_idx=0;
for(size_t i=0;i<size;i++){
target[i]=source[i]^key[key_idx];
key_idx++;
key_idx&=0x3;
}
}
void f__WebSocket__Encode(const WebSocket__PDU& pl__pdu, OCTETSTRING& pl__data,
const BOOLEAN& pl__gen__maks, const BOOLEAN& pl__auto__maks){
TTCN_Buffer buff;
unsigned char* data_ptr=NULL;
size_t payload_size=0;
if(pl__pdu.payload__data().ispresent()){
if(pl__pdu.payload__data()().ischosen(WebSocket__payloads::ALT_data)){
payload_size=pl__pdu.payload__data()().data().lengthof();
} else {
payload_size=2;
if(pl__pdu.payload__data()().close__data().data().ispresent()){
payload_size+=pl__pdu.payload__data()().close__data().data()().lengthof();
}
}
}
size_t data_size=14+payload_size; // max header size + payload size
buff.get_end(data_ptr,data_size);
unsigned char* begin_ptr=data_ptr;
memset(data_ptr,0,data_size);
*data_ptr|=((*((const unsigned char*)pl__pdu.fin__bit()))&0x1)<<7;
*data_ptr|=((*((const unsigned char*)pl__pdu.rsv1__bit()))&0x1)<<6;
*data_ptr|=((*((const unsigned char*)pl__pdu.rsv2__bit()))&0x1)<<5;
*data_ptr|=((*((const unsigned char*)pl__pdu.rsv3__bit()))&0x1)<<4;
*data_ptr|=((int)pl__pdu.opcode())&0xf;
data_ptr++;
*data_ptr|=((*((const unsigned char*)pl__pdu.mask__bit()))&0x1)<<7;
// encode size
if(payload_size<126){
*data_ptr|=(payload_size&0x7);
data_ptr++;
} else if (payload_size<65536) { // 16 bit unsigned max
size_t orig_p_size=payload_size;
*data_ptr|=126;
data_ptr++;
data_ptr[1]=orig_p_size&0xff;
orig_p_size>>=8;
data_ptr[0]=orig_p_size&0xff;
data_ptr+=2;
} else {
size_t orig_p_size=payload_size;
*data_ptr|=127;
data_ptr++;
data_ptr[7]=orig_p_size&0xff;
orig_p_size>>=8;
data_ptr[6]=orig_p_size&0xff;
orig_p_size>>=8;
data_ptr[5]=orig_p_size&0xff;
orig_p_size>>=8;
data_ptr[4]=orig_p_size&0xff;
orig_p_size>>=8;
data_ptr[3]=orig_p_size&0xff;
orig_p_size>>=8;
data_ptr[2]=orig_p_size&0xff;
orig_p_size>>=8;
data_ptr[1]=orig_p_size&0xff;
orig_p_size>>=8;
data_ptr[0]=orig_p_size&0xff;
data_ptr+=8;
}
unsigned char* mask_ptr=NULL;
if(((*((const unsigned char*)pl__pdu.mask__bit()))&0x1) &&
pl__gen__maks &&
(!pl__pdu.masking__key().ispresent() ||
pl__pdu.masking__key()()==zero_oct)){
// generate masking key
mask_ptr=data_ptr;
OCTETSTRING mk=f__WebSocket__Generate__Masking__Key();
memcpy(data_ptr,(const unsigned char *)mk,4);
data_ptr+=4;
} else if(pl__pdu.masking__key().ispresent()) { // use the provided key
mask_ptr=data_ptr;
memcpy(data_ptr,(const unsigned char *)pl__pdu.masking__key()(),4);
data_ptr+=4;
}
if(pl__pdu.payload__data().ispresent()){
if(pl__pdu.payload__data()().ischosen(WebSocket__payloads::ALT_data)){
memcpy(data_ptr,
(const unsigned char *)pl__pdu.payload__data()().data(),
pl__pdu.payload__data()().data().lengthof());
} else {
int st_code=(int)pl__pdu.payload__data()().close__data().status__code();
data_ptr[1]=st_code&0xFF;
st_code>>=8;
data_ptr[0]=st_code&0xFF;
if(pl__pdu.payload__data()().close__data().data().ispresent()){
memcpy(data_ptr+2, // skip status code
(const unsigned char *)pl__pdu.payload__data()().close__data().data()(),
pl__pdu.payload__data()().close__data().data()().lengthof());
}
}
}
if(mask_ptr && pl__auto__maks){ // apply mask
do_mask(mask_ptr,data_ptr,data_ptr,payload_size);
}
buff.increase_length(data_ptr-begin_ptr+payload_size);
buff.get_string(pl__data);
}
INTEGER f__WebSocket__Decode(const OCTETSTRING& pl__data,
WebSocket__PDU& pl__pdu, const BOOLEAN& pl__auto__maks){
size_t data_len=pl__data.lengthof();
if(data_len>=2){
const unsigned char* data_ptr=(const unsigned char*)pl__data;
size_t base_length=(data_ptr[1]&0x80)?6:2;
size_t payload_length=data_ptr[1]&0x7F;
size_t len_len=0;
if (payload_length==126) {
if(data_len>=4){
payload_length=(data_ptr[2]<<8)+data_ptr[3];
len_len=2;
} else {
return 1; // NOT_MY_TYPE not enough bits in the buffer
}
} else if (payload_length==127) {
if(data_len>=10){
len_len=8;
long long int large_payload_length=(((long long int)data_ptr[2])<<56)+
(((long long int)data_ptr[3])<<48)+(((long long int)data_ptr[4])<<40)+
(((long long int)data_ptr[5])<<32)+(((long long int)data_ptr[6])<<24)+
(((long long int)data_ptr[7])<<16)+(((long long int)data_ptr[8])<<8)+
(long long int)data_ptr[9];
payload_length=large_payload_length;
if(large_payload_length!=(long long int)payload_length){ // overflow
TTCN_warning("The received WebSocket messages is too large");
return 1; // NOT_MY_TYPE message too largo to handle
}
} else {
return 1; // NOT_MY_TYPE not enough bits in the buffer
}
}
if(data_len<(payload_length+base_length)){
return 1; // NOT_MY_TYPE not enough bits in the buffer
}
// Now the decodeing can be started.
unsigned char bit_temp;
bit_temp=(data_ptr[0]>>7)&0x1;
pl__pdu.fin__bit()=BITSTRING(1,&bit_temp);
bit_temp=(data_ptr[0]>>6)&0x1;
pl__pdu.rsv1__bit()=BITSTRING(1,&bit_temp);
bit_temp=(data_ptr[0]>>5)&0x1;
pl__pdu.rsv2__bit()=BITSTRING(1,&bit_temp);
bit_temp=(data_ptr[0]>>4)&0x1;
pl__pdu.rsv3__bit()=BITSTRING(1,&bit_temp);
pl__pdu.opcode()=data_ptr[0]&0xf;
bit_temp=(data_ptr[1]>>7)&0x1;
bool masked=bit_temp;
pl__pdu.mask__bit()=BITSTRING(1,&bit_temp);
pl__pdu.payload__len()=payload_length;
data_ptr+=len_len+2;
unsigned char* unmasked=NULL;
if(masked){
pl__pdu.masking__key()=OCTETSTRING(4,data_ptr);
if(pl__auto__maks && payload_length){
unmasked=(unsigned char*)Malloc(payload_length*sizeof(unsigned char));
do_mask(data_ptr,data_ptr+4,unmasked,payload_length);
data_ptr=unmasked;
} else {
data_ptr+=4;
}
} else {
pl__pdu.masking__key()=OMIT_VALUE;
}
if(payload_length){
if(pl__pdu.opcode()==WebSocket__opcode::Connection__Close){
if(payload_length>=2){
pl__pdu.payload__data()().close__data().status__code()=
(data_ptr[0]<<8) + data_ptr[1];
if(payload_length>2){
pl__pdu.payload__data()().close__data().data()()=
OCTETSTRING(payload_length-2,data_ptr+2);
} else {
pl__pdu.payload__data()().close__data().data()=OMIT_VALUE;
}
} else {
return 1; // NOT_MY_TYPE not enough bits in the buffer
}
} else {
pl__pdu.payload__data()().data()=OCTETSTRING(payload_length,data_ptr);
}
} else {
pl__pdu.payload__data()=OMIT_VALUE;
}
if(unmasked) {
Free(unmasked);
}
} else {
return 1; // NOT_MY_TYPE not enough bits in the buffer
}
return 0;
}
INTEGER f__WebSocket__calc__length(const OCTETSTRING& pl__data){
size_t data_len=pl__data.lengthof();
if(data_len>=2){
const unsigned char* data_ptr=(const unsigned char*)pl__data;
int base_length=(data_ptr[1]&0x80)?6:2;
int payload_length=data_ptr[1]&0x7F;
if(payload_length<126){
return payload_length+base_length;
} else if (payload_length==126) {
if(data_len>=4){
payload_length=(data_ptr[2]<<8)+data_ptr[3];
return payload_length+base_length+2;
}
} else {
if(data_len>=10){
long long int large_payload_length=(((long long int)data_ptr[2])<<56)+
(((long long int)data_ptr[3])<<48)+(((long long int)data_ptr[4])<<40)+
(((long long int)data_ptr[5])<<32)+(((long long int)data_ptr[6])<<24)+
(((long long int)data_ptr[7])<<16)+(((long long int)data_ptr[8])<<8)+
(long long int)data_ptr[9]+(long long int)base_length+8;
INTEGER large_ret_val;
large_ret_val.set_long_long_val(large_payload_length);
return large_ret_val;
}
}
}
return -1;
}
OCTETSTRING f__WebSocket__Generate__Masking__Key(){
static bool inited=false;
if(!inited){
time_t t1;
time(&t1);
srand48((long) t1);
inited=true;
}
unsigned char mkey[4];
long int key=mrand48();
mkey[0]= key & 0xFF;
key>>=8;
mkey[1]= key & 0xFF;
key>>=8;
mkey[2]= key & 0xFF;
key>>=8;
mkey[3]= key & 0xFF;
return OCTETSTRING(4,&mkey[0]);
}
}
/******************************************************************************
* Copyright (c) 2005, 2015 Ericsson AB
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Gabor Szalai
******************************************************************************/
//
// File: WebSocket_Types.ttcn
// Rev: R2A
// Prodnr: CNL 113 782
// Reference: RFC 6455
module WebSocket_Types {
modulepar boolean m_Websocket_generate_masking_key:=true;
modulepar boolean m_Websocket_auto_masking:=true;
external function f_WebSocket_Encode(in WebSocket_PDU pl_pdu,
out octetstring pl_data,
in boolean pl_gen_maks:=m_Websocket_generate_masking_key,
in boolean pl_auto_maks:= m_Websocket_auto_masking);
external function f_WebSocket_Decode(in octetstring pl_data,
out WebSocket_PDU pl_pdu,
in boolean pl_auto_maks:= m_Websocket_auto_masking)
return integer;
external function f_WebSocket_calc_length(in octetstring pl_data)
return integer;
external function f_WebSocket_Generate_Masking_Key() return octetstring;
type record Websocket_close {
integer status_code,
octetstring data optional
};
type enumerated WebSocket_opcode {Continuation_frame (0), Text_frame (1),
Binary_frame (2), Reserved_non_control3 (3),
Reserved_non_control4 (4),
Reserved_non_control5 (5),
Reserved_non_control6 (6),
Reserved_non_control7 (7),
Connection_Close(8), Ping(9), Pong (10),
Reserved_control11 (11),
Reserved_control12 (12),
Reserved_control13 (13),
Reserved_control14 (14),
Reserved_control15 (15)
};
type union WebSocket_payloads {
octetstring data,
Websocket_close close_data
};
type record WebSocket_PDU {
bitstring fin_bit length(1),
bitstring rsv1_bit length(1),
bitstring rsv2_bit length(1),
bitstring rsv3_bit length(1),
WebSocket_opcode opcode,
bitstring mask_bit length(1),
integer payload_len,
octetstring masking_key length(4) optional,
WebSocket_payloads payload_data optional
};
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment