@ -100,6 +100,7 @@ struct ast_websocket {
unsigned int closing : 1 ; /*!< Bit to indicate that the session is in the process of being closed */
unsigned int close_sent : 1 ; /*!< Bit to indicate that the session close opcode has been sent and no further data will be sent */
struct websocket_client * client ; /*!< Client object when connected as a client websocket */
uint16_t close_status_code ; /*!< Status code sent in a CLOSE frame upon shutdown */
} ;
/*! \brief Hashing function for protocols */
@ -181,7 +182,7 @@ static void session_destroy_fn(void *obj)
struct ast_websocket * session = obj ;
if ( session - > f ) {
ast_websocket_close ( session , 0 ) ;
ast_websocket_close ( session , session - > close_status_code ) ;
if ( session - > f ) {
fclose ( session - > f ) ;
ast_verb ( 2 , " WebSocket connection %s '%s' closed \n " , session - > client ? " to " : " from " ,
@ -566,7 +567,7 @@ int AST_OPTIONAL_API_NAME(ast_websocket_read)(struct ast_websocket *session, cha
* opcode = buf [ 0 ] & 0xf ;
* payload_len = buf [ 1 ] & 0x7f ;
if ( * opcode = = AST_WEBSOCKET_OPCODE_TEXT | | * opcode = = AST_WEBSOCKET_OPCODE_BINARY | | * opcode = = AST_WEBSOCKET_OPCODE_CONTINUATION | |
* opcode = = AST_WEBSOCKET_OPCODE_PING | | * opcode = = AST_WEBSOCKET_OPCODE_PONG ) {
* opcode = = AST_WEBSOCKET_OPCODE_PING | | * opcode = = AST_WEBSOCKET_OPCODE_PONG | | * opcode = = AST_WEBSOCKET_OPCODE_CLOSE ) {
fin = ( buf [ 0 ] > > 7 ) & 1 ;
mask_present = ( buf [ 1 ] > > 7 ) & 1 ;
@ -622,6 +623,16 @@ int AST_OPTIONAL_API_NAME(ast_websocket_read)(struct ast_websocket *session, cha
return 0 ;
}
/* Save the CLOSE status code which will be sent in our own CLOSE in the destructor */
if ( * opcode = = AST_WEBSOCKET_OPCODE_CLOSE ) {
session - > closing = 1 ;
if ( * payload_len > = 2 ) {
session - > close_status_code = ntohs ( get_unaligned_uint16 ( * payload ) ) ;
}
* payload_len = 0 ;
return 0 ;
}
if ( * payload_len ) {
if ( ! ( new_payload = ast_realloc ( session - > payload , ( session - > payload_len + * payload_len ) ) ) ) {
ast_log ( LOG_WARNING , " Failed allocation: %p, %zu, % " PRIu64 " \n " ,
@ -661,28 +672,6 @@ int AST_OPTIONAL_API_NAME(ast_websocket_read)(struct ast_websocket *session, cha
* payload = session - > payload ;
session - > payload_len = 0 ;
}
} else if ( * opcode = = AST_WEBSOCKET_OPCODE_CLOSE ) {
session - > closing = 1 ;
/* Make the payload available so the user can look at the reason code if they so desire */
if ( ! * payload_len ) {
return 0 ;
}
if ( ! ( new_payload = ast_realloc ( session - > payload , * payload_len ) ) ) {
ast_log ( LOG_WARNING , " Failed allocation: %p, % " PRIu64 " \n " ,
session - > payload , * payload_len ) ;
* payload_len = 0 ;
return - 1 ;
}
session - > payload = new_payload ;
if ( ws_safe_read ( session , & buf [ frame_size ] , * payload_len , opcode ) ) {
return - 1 ;
}
memcpy ( session - > payload , & buf [ frame_size ] , * payload_len ) ;
* payload = session - > payload ;
frame_size + = * payload_len ;
} else {
ast_log ( LOG_WARNING , " WebSocket unknown opcode %u \n " , * opcode ) ;
/* We received an opcode that we don't understand, the RFC states that 1003 is for a type of data that can't be accepted... opcodes