示例#1
0
///@note this function is a recent inclusion, but it's not used.  Don't use it
/// until new ALP is stable, if it is still here.
OT_WEAK void alp_load_header(ot_queue* appq, alp_record* rec) {
    rec->flags      = q_readbyte(appq);
    rec->plength    = q_readbyte(appq);
    rec->id         = q_readbyte(appq);
    rec->cmd        = q_readbyte(appq);
    //q_readstring(appq, (ot_u8*)&rec->flags, 4);  //works only on packed structs
}
示例#2
0
OT_WEAK void alp_breakdown_udp_tmpl(ot_queue* in_q, void* data_type) {
    ot_int udp_data_length;
    udp_data_length                       = q_readshort(in_q);
    ((udp_tmpl*)data_type)->data_length   = udp_data_length;
    ((udp_tmpl*)data_type)->dst_port      = q_readbyte(in_q);
    ((udp_tmpl*)data_type)->src_port      = q_readbyte(in_q);
    ((udp_tmpl*)data_type)->data          = q_markbyte(in_q, udp_data_length);
}
示例#3
0
OT_WEAK void alp_breakdown_ack_tmpl(ot_queue* in_q, void* data_type) {
    ot_int ack_id_count;
    ot_int ack_id_length;
    ack_id_count                    = q_readbyte(in_q);
    ack_id_length                   = q_readbyte(in_q);
    ((ack_tmpl*)data_type)->count   = (ot_u8)ack_id_count;
    ((ack_tmpl*)data_type)->length  = (ot_u8)ack_id_length;
    ((ack_tmpl*)data_type)->list    = q_markbyte(in_q, ack_id_count*ack_id_length);
}
示例#4
0
OT_WEAK void alp_breakdown_dialog_tmpl(ot_queue* in_q, void* data_type) {
    ((dialog_tmpl*)data_type)->timeout = q_readbyte(in_q);
    
    if (((dialog_tmpl*)data_type)->timeout & 0x80) {
        ((dialog_tmpl*)data_type)->channels = q_readbyte(in_q);
        ((dialog_tmpl*)data_type)->chanlist = \
            q_markbyte(in_q, ((dialog_tmpl*)data_type)->channels);
    }
}
示例#5
0
ot_int sub_fileheaders( alp_tmpl* alp, id_tmpl* user_id, ot_u8 respond, ot_u8 cmd_in, ot_int data_in ) {
    ot_int  data_out    = 0;
    vlBLOCK file_block  = (vlBLOCK)((cmd_in >> 4) & 0x07);

    /// Only run if respond bit is set!
    if (respond) {
        while ((data_in > 0) && sub_qnotfull(respond, 6, alp->outq)) {
            vaddr   header;
            ot_bool allow_output = True;
            
            data_in--;  // one for the file id
            
            allow_output = (ot_bool)(vl_getheader_vaddr(&header, file_block, \
                                    q_readbyte(alp->inq), VL_ACCESS_R, NULL) == 0);
            if (allow_output) {
                q_writeshort_be(alp->outq, vworm_read(header + 4)); // id & mod
                q_writeshort(alp->outq, vworm_read(header + 0)); // length
                q_writeshort(alp->outq, vworm_read(header + 2)); // alloc
                data_out += 6;
            }
        }
        
        //alp->BOOKMARK_IN = (void*)sub_testchunk(data_in);
    }
    
    return data_out; 
}
示例#6
0
OT_WEAK void alp_breakdown_query_tmpl(ot_queue* in_q, void* data_type) {
    ot_u8   query_length;
    ot_u8   query_code;
    ot_u8*  query_mask;
    
    query_code      = q_readbyte(in_q);
    query_length    = q_readbyte(in_q);
    query_mask      = NULL;
    
    if (query_code & 0x80) {
        query_mask  = q_markbyte(in_q, query_length);
    }
    
    ((query_tmpl*)data_type)->code      = query_code;
    ((query_tmpl*)data_type)->length    = query_length;
    ((query_tmpl*)data_type)->mask      = query_mask;
    ((query_tmpl*)data_type)->value     = q_markbyte(in_q, query_length);
}
示例#7
0
ot_int sub_fileperms( alp_tmpl* alp, id_tmpl* user_id, ot_u8 respond, ot_u8 cmd_in, ot_int data_in ) {
    ot_int  data_out    = 0;
    vlBLOCK file_block  = (vlBLOCK)((cmd_in >> 4) & 0x07);
    ot_u8   file_mod    = ((cmd_in & 0x02) ? VL_ACCESS_W : VL_ACCESS_R);

    /// Loop through all the listed file ids and process permissions.
    while ((data_in > 0) && sub_qnotfull(respond, 2, alp->outq)) {
        ot_u8   file_id         = q_readbyte(alp->inq);
        ot_bool allow_write     = respond;
        vaddr   header;
        
        data_in--;  // one for the file id
        
        if (file_mod == VL_ACCESS_W ) {
            /// run the chmod and return the error code (0 is no error)
            data_in--;  // two for the new mod
            file_mod = vl_chmod(file_block, file_id, q_readbyte(alp->inq), user_id);
        }
        else if (allow_write) {
            /// Get the header address and return mod (offset 5).  The root user
            /// (NULL) is used because this is only for reading filemod.
            /// Note: This is a hack that is extremely optimized for speed
            allow_write = (ot_bool)(vl_getheader_vaddr(&header, file_block, file_id, \
                                                    VL_ACCESS_R, NULL) == 0);
            if (allow_write) {
                Twobytes filemod;
                filemod.ushort  = vworm_read(header + 4);   //shortcut to idmod, hack-ish but fast
                file_mod        = filemod.ubyte[1];
            }
        }
        if (allow_write) {
            /// load the data onto the output, if response enabled
            q_writebyte(alp->outq, file_id);
            q_writebyte(alp->outq, file_mod);
            data_out += 2;
        }
    }
    
    /// return number of bytes put onto the output (always x2)
    //alp->BOOKMARK_IN = (void*)sub_testchunk(data_in);
    return data_out;
}
示例#8
0
OT_WEAK void alp_breakdown_routing_tmpl(ot_queue* in_q, void* data_type) {
    ot_u8 id_length;
    ot_u8 code_mask;
    ((routing_tmpl*)data_type)->hop_code    = q_readbyte(in_q);
    ((routing_tmpl*)data_type)->hop_ext     = q_readbyte(in_q);
    
    alp_breakdown_id_tmpl(in_q, (void*)&((routing_tmpl*)data_type)->dlog);
    
    if (((routing_tmpl*)data_type)->hop_code > 1) {
        code_mask                               = (((routing_tmpl*)data_type)->hop_ext != 0) << 7;
        id_length                               = q_readbyte(in_q);
        ((routing_tmpl*)data_type)->orig.length = id_length;
        code_mask                              |= (id_length != 0) << 6;
        code_mask                              |= (id_length == 2) << 4;
        ((routing_tmpl*)data_type)->orig.value  = q_markbyte(in_q, id_length);
        id_length                               = q_readbyte(in_q);
        ((routing_tmpl*)data_type)->dest.length = id_length;
        code_mask                              |= (id_length != 0) << 5;
        code_mask                              |= (id_length == 2) << 4;
        ((routing_tmpl*)data_type)->dest.value  = q_markbyte(in_q, id_length);
        ((routing_tmpl*)data_type)->hop_code   |= code_mask;
    }
}
示例#9
0
/// Not currently supported, always returns "unrestorable" error
ot_int sub_filerestore(alp_tmpl* alp, id_tmpl* user_id, ot_u8 respond, ot_u8 cmd_in, ot_int data_in ) {
    ot_int  data_out    = 0;
    //vlBLOCK file_block  = ((cmd_in >> 4) & 0x07);
    
    while ((data_in > 0) && sub_qnotfull(respond, 2, alp->outq)) {
        ot_u8   err_code    = 0x03;
        ot_u8   file_id     = q_readbyte(alp->inq);
        data_in            -= 1;
    
        if (respond) {
            q_writebyte(alp->outq, file_id);
            q_writebyte(alp->outq, err_code);
            data_out += 2;
        }
    }    
    
    //alp->BOOKMARK_IN = (void*)sub_testchunk(data_in);
    return data_out;     
}
示例#10
0
ot_int sub_filedata( alp_tmpl* alp, id_tmpl* user_id, ot_u8 respond, ot_u8 cmd_in, ot_int data_in ) {
    vlFILE* fp;
    ot_u16  offset;
    ot_u16  span;
    ot_int  data_out    = 0;
    ot_bool inc_header  = (ot_bool)((cmd_in & 0x0F) == 0x0C);
    vlBLOCK file_block  = (vlBLOCK)((cmd_in >> 4) & 0x07);
    ot_u8   file_mod    = ((cmd_in & 0x02) ? VL_ACCESS_W : VL_ACCESS_R);
    ot_queue*  inq      = alp->inq;
    ot_queue*  outq     = alp->outq;
    
    sub_filedata_TOP:
    
    while (data_in > 0) {
        vaddr   header;
        ot_u8   err_code;
        ot_u8   file_id;
        ot_u16  limit;
        
        //alp->BOOKMARK_IN    = inq->getcursor;
        //alp->BOOKMARK_OUT   = NULL;
        
        file_id     = q_readbyte(inq);
        offset      = q_readshort(inq);
        span        = q_readshort(inq);
        limit       = offset + span;
        err_code    = vl_getheader_vaddr(&header, file_block, file_id, file_mod, user_id);
        file_mod    = ((file_mod & VL_ACCESS_W) != 0);
        //fp          = NULL;
        
        // A. File error catcher Stage
        // (In this case, gotos make it more readable)
        
        /// Make sure file header was retrieved properly, or goto error
        if (err_code != 0) {
            goto sub_filedata_senderror;
        }
        
        /// Make sure file opens properly, or goto error
        fp = vl_open_file(header);
        if (fp == NULL) {
            err_code = 0xFF;
            goto sub_filedata_senderror;
        }
        
        /// Make sure offset is within file bounds, or goto error
        if (offset >= fp->alloc) {
            err_code = 0x07;
            goto sub_filedata_senderror;
        }
        
        if (limit > fp->alloc) {
            limit       = fp->alloc;
            err_code    = 0x08;
        }

        // B. File Writing or Reading Stage
        // Write to file
        // 1. Process error on bad ALP parameters, but still do partial write
        // 2. offset, span are adjusted to convey leftover data
        // 3. miscellaneous write error occurs when vl_write fails
        if (file_mod) {
            for (; offset<limit; offset+=2, span-=2, data_in-=2) {
                if (inq->getcursor >= inq->back) {
                    goto sub_filedata_overrun;      
                }
                err_code |= vl_write(fp, offset, q_readshort_be(inq));
            }
        }
        
        // Read from File
        // 1. No error for bad read parameter, just fix the limit
        // 2. If inc_header param is set, include the file header in output
        // 3. Read out file data
        else {
            ot_u8 overhead;
            //limit       = (limit > fp->length) ? fp->length : limit;
            overhead    = 6;
            overhead   += (inc_header != 0) << 2; 
            
            if ((outq->putcursor+overhead) >= outq->back) {
                goto sub_filedata_overrun;
            }
            
            q_writeshort_be(outq, vworm_read(header + 4)); // id & mod
            if (inc_header) {
                q_writeshort(outq, vworm_read(header + 0));    // length
                q_writeshort(outq, vworm_read(header + 2));    // alloc
                data_out += 4;
            }
            q_writeshort(outq, offset);
            q_writeshort(outq, span);
            data_out += 6;
            
            for (; offset<limit; offset+=2, span-=2, data_out+=2) {
                if ((outq->putcursor+2) >= outq->back) {
                    goto sub_filedata_overrun;
                }
                q_writeshort_be(outq, vl_read(fp, offset));
            }
        }
        
        // C. Error Sending Stage
        sub_filedata_senderror:
        if ((respond != 0) && (err_code | file_mod)) {
            if ((outq->putcursor+2) >= outq->back) {
                goto sub_filedata_overrun;
            }
            q_writebyte(outq, file_id);
            q_writebyte(outq, err_code);
            q_markbyte(inq, span);         // go past any leftover input data
            data_out += 2;
        }
        
        data_in -= 5;   // 5 bytes input header
        vl_close(fp);
    }
    
    
    // Total Completion:
    // Set bookmark to NULL, because the record was completely processed
    //alp->BOOKMARK_IN = NULL;
    return data_out;
    
    
    // Partial or Non Completion:
    // Reconfigure last ALP operation, because it was not completely processed
    
    ///@todo Bookmarking is obsolete, because the way Chunking is done has
    /// been revised.  Chunked records must be contiguous.  ALP-Main will not
    /// call this app, and thus not call this function, until the message-end
    /// bit is detected, therefore meaning that all data is received and
    /// contiguous.  This overrun block, thus, should only check the flags for
    /// chunking, bypass them, and loop back to the top of this function.
    sub_filedata_overrun:
    vl_close(fp);
    
    ///@todo alp_next_chunk(alp);
    
//    {
//        ot_u8* scratch;
//        inq->getcursor  = (ot_u8*)alp->BOOKMARK_IN;
//        scratch         = inq->getcursor + 1;
//        *scratch++      = ((ot_u8*)&offset)[UPPER];
//        *scratch++      = ((ot_u8*)&offset)[LOWER];
//        *scratch++      = ((ot_u8*)&span)[UPPER];
//        *scratch        = ((ot_u8*)&span)[LOWER];
//    }
    
    return data_out;
}
示例#11
0
ot_int sub_parse_request(m2session* session) {
    ot_int  score   = 0;
    ot_u8   cmd_opcode;
    //ot_u8   nack    = 0;

    /// 1.  Universal Comm Processing                                       <BR>
    ///     - Load CCA type & CSMA disable from command extension           <BR>
    ///     - Load NA2P or A2P dialog type from command code
    m2qp.cmd.code           = q_readbyte(&rxq);
    m2qp.cmd.ext            = (m2qp.cmd.code & 0x80) ? q_readbyte(&rxq) : 0;
    dll.comm.csmaca_params  = m2qp.cmd.ext & (M2_CSMACA_CAMASK | M2_CSMACA_NOCSMA);
    dll.comm.csmaca_params |= m2qp.cmd.code & M2_CSMACA_ARBMASK;
    cmd_opcode              = m2qp.cmd.code & M2OP_MASK;

    /// 2.  All Requests contain the dialog template, so load it.           <BR>
    ///     - [ num resp channels ] [ list of resp channels]                <BR>
    ///     - if number of resp channels is 0, use the current channel
    {
        ot_u8 timeout_code  = q_readbyte(&rxq);
        dll.comm.rx_timeout = otutils_calc_timeout(timeout_code);    // original contention period
        dll.comm.tc         = dll.comm.rx_timeout;  // contention period counter

        if (timeout_code & 0x80) {
            dll.comm.tx_channels    = q_readbyte(&rxq);
            dll.comm.tx_chanlist    = q_markbyte(&rxq, dll.comm.tx_channels);
        }
        else {
            dll.comm.tx_channels    = 1;
            dll.comm.tx_chanlist    = &dll.comm.scratch[0];
            dll.comm.scratch[0]     = session->channel;
        }
    }

    /// 3. Handle Command Queries (filtering)                               <BR>
    /// Multicast and anycast addressed requests include queries
    if (m2np.header.addr_ctl & 0x80) {
        score = sub_process_query(session);
    }

    /// 4. If the query is good (sometimes this is trivial):                <BR>
    ///    - Prepare the response header (same for all responses)           <BR>
    ///    - Run command-specific dialog data processing
    if (score >= 0) {
        q_empty(&txq); // Flush TX Queue

        if (m2qp.cmd.ext & M2CE_NORESP) {
            session->netstate  |= M2_NETFLAG_SCRAP;
        }
        else {
            ot_u8 addressing;
            session->netstate  &= ~M2_NETSTATE_TMASK;
            session->netstate  |= M2_NETSTATE_RESPTX;
            addressing          = ext_get_m2appflags();
            addressing         |= m2np.header.addr_ctl & 0x30;  // make unicast, retain VID & NLS
            m2np_header(session, addressing, 0);                // Create M2QP header
            q_writebyte(&txq, (M2TT_RESPONSE | cmd_opcode));    // Write Cmd code byte
        }

        switch ((cmd_opcode>>1) & 7) {
        case 0:
        case 1:
            break;
        case 2:
            sub_opgroup_shell();
            break;
        case 3:
        case 4:
            sub_opgroup_collection();
            break;
        case 5:
            break;
        case 6:
            sub_opgroup_datastream();
            break;
        case 7:
            sub_ack_datastream();
            break;
        }
    }
示例#12
0
ot_int sub_parse_response(m2session* session) {
/// Only Gateways and Subcontrollers do anything with the response.  Generally,
/// Gateways might have some sort of logging in the callbacks.  Response types
/// include: (1) Normal responses to NA2P standard dialog, (2) Arbitrated
/// responses to A2P multicast dialog, (3) Responses that are part of 2, 3, 4,
/// or 5-way datastream session.
    ot_u8   test;
    ot_u8   cmd_opcode;

    /// Make sure response command opcode matches the last request's opcode
    /// (this ensures that the response is to our request).
    cmd_opcode  = m2qp.cmd.code & 0x0F;
    test        = q_readbyte(&rxq) & 0x0F;

    if (test == cmd_opcode) {
#       if ((M2_FEATURE(DATASTREAM) == ENABLED) && (OT_FEATURE(ALP) == ENABLED))
        /// Manage Responses to Request and Propose Datastream
        if ((cmd_opcode - M2OP_DS_REQUEST) <= 1) {
            ot_u16  ds_total_bytes  = q_readshort(&rxq);    // might be removed
            ot_u8   fr_per_pkt      = q_readbyte(&rxq);     // might be removed
            ot_u8   num_frames      = rxq.getcursor[0];     // might be removed
            rxq.getcursor          += ((cmd_opcode & 1) == 0);
            m2dp.out_rec.flags      = ALP_FLAG_MB;          // ds beginning

            // Run Callback (if enabled).  Callback can override processing
            // (Callback is not compiled when callbacks are disabled)
            test = (ot_u8)M2QP_CALLBACK(DSPKT);
            if ( test ) {
                m2dp_dsproc();
            }
            ///@todo Might put in some type of return scoring, later
            return (ot_int)test;
        }
#           if (OT_FEATURE(M2QP_CALLBACKS) == ENABLED)
        else if (cmd_opcode == 10) {
            test = (ot_u8)M2QP_CALLBACK(DSACK);
            if ( test ) {
                ///@todo Prepare the next stream packet
            }
            return (ot_int)test;
        }
#           endif
        else if (((m2qp.cmd.code & 0x60) == 0x40) && \
                 ((txq.back - txq.putcursor) > 48) )

#       else //((M2_FEATURE(DATASTREAM) == ENABLED) && (OT_FEATURE(ALP) == ENABLED))
        if (((m2qp.cmd.code & 0x60) == 0x40) && \
                ((txq.back - txq.putcursor) > 48) )
#       endif

            /// If using A2P, put this responder's ID onto the ACK chain        <BR>
            /// - Reserve some room at the back for query data (48 bytes)       <BR>
            /// - Increment "Number of ACKs" on each use (txq.getcursor[0])     <BR>
            /// - Run the A2P callback (if enabled)
        {
            ///@todo check to make sure NumACKs is 0 on 1st run (might be done)
            ///@todo Might put in some type of return scoring, later
            txq.getcursor[0]++;
            q_writestring(&txq, m2np.rt.dlog.value, m2np.rt.dlog.length);
            test = (ot_u8)M2QP_CALLBACK(A2P);
        }

        /// If nothing else, the response is a normal response (NA2P), so run
        /// the callback as normal
        else {
            test = (ot_u8)M2QP_CALLBACK(STANDARD);
        }

        /// Make into 0/-1 form for returning
        return (ot_int)test - 1;
    }
}
示例#13
0
OT_WEAK void alp_breakdown_u8(ot_queue* in_q, void* data_type) {
    *(ot_u8*)data_type = q_readbyte(in_q); 
}
示例#14
0
OT_WEAK void alp_breakdown_error_tmpl(ot_queue* in_q, void* data_type) {
    ((error_tmpl*)data_type)->code      = q_readbyte(in_q);
    ((error_tmpl*)data_type)->subcode   = q_readbyte(in_q);
    ((error_tmpl*)data_type)->data      = in_q->getcursor;  ///@todo build a routine for code:subcode --> data length
}
示例#15
0
OT_WEAK void alp_breakdown_id_tmpl(ot_queue* in_q, void* data_type) {
    ot_int id_length;
    id_length                       = q_readbyte(in_q);
    ((id_tmpl*)data_type)->length   = id_length;
    ((id_tmpl*)data_type)->value    = (id_length==0) ? NULL : q_markbyte(in_q, id_length);
}
示例#16
0
ot_int network_route_ff(m2session* session) {
    ot_int route_val;

    /// Strip CRC (-2 bytes)
    rxq.front[0] -= 2;
    
    /// Acquire Flags and Protocol from the Frame Info Field
    rxq.getcursor       = &rxq.front[3];
    session->protocol   = (*rxq.getcursor & M2FI_FRTYPEMASK);
    session->flags      = *rxq.getcursor & 0xC0;
    m2np.header.fr_info = *rxq.getcursor++;
    
    /// Treat Non-Mode-2 Protocols
    /// @note Non-Mode-2 protocols not supported at this time
    if (m2np.header.fr_info & M2FI_NM2) {
        return -1;
    }
    
    /// Data Link Layer Security
    if (m2np.header.fr_info & M2FI_DLLS) {
#   if (OT_FEATURE(DLL_SECURITY))
        ///@todo experimental
        AES_load_static_key(ISF_ID(user_authentication_key), (ot_u32*)txq.front);
        AES_keyschedule_dec((ot_u32*)txq.front, (ot_u32*)(txq.front+16));
        AES_decrypt(rxq.getcursor, rxq.getcursor, (ot_u32*)(txq.front+16));
#   else
        return -1;
#   endif
    }
    
    /// Address Control Header (Present in M2NP)
    /// Session Connection and Dialog Filtering:
    /// - if unassociated, connect now
    /// - if already connected, make sure the dialog IDs are equal
    if (m2np.header.fr_info & M2FI_ENADDR) {
        if (session->netstate & M2_NETSTATE_CONNECTED) {
            if (session->dialog_id != q_readbyte(&rxq)) {
                return -1;
            }
        }
        else {
            session->netstate  |= M2_NETSTATE_CONNECTED;
            session->subnet     = rxq.front[2];
            session->dialog_id  = q_readbyte(&rxq);
        }
        
        /// Grab global flags from Address Control
        m2np.header.addr_ctl    = q_readbyte(&rxq);
        session->flags         |= m2np.header.addr_ctl & 0x3F;
        
        /// Grab Source Address from this packet (dialog address), which is 
        /// converted to the target address in the response.
        m2np.rt.dlog.length = (m2np.header.addr_ctl & M2_FLAG_VID) ? 2 : 8;
        m2np.rt.dlog.value  = q_markbyte(&rxq, m2np.rt.dlog.length);
        
        /// Network Layer Security
        /// @note Network Layer Security not supported at this time
        if (m2np.header.addr_ctl & M2_FLAG_NLS) {
#       if (OT_FEATURE(NL_SECURITY))
#       else
            return -1;
#       endif
        }
        
        /// If unicasting, the next data is the target address, which will have
        /// the same length as the source address, and it needs to match this
        /// device's device ID (VID or UID)
        if ((m2np.header.addr_ctl & 0xC0) == 0) {
            session->netstate |= M2_NETFLAG_FIRSTRX;
            if ( !m2np_idcmp(m2np.rt.dlog.length, q_markbyte(&rxq, m2np.rt.dlog.length)) ) {
                return -1;
            }
        }
    }

    /// Vector to the appropriate Network Layer Protocol Parser
    /// Most network protocols don't do anything except broadcast.  M2NP is the
    /// exception, and it manages various types of routing at the network layer.
    route_val = -1;
    switch (session->protocol & M2FI_FRTYPEMASK) {
    	case M2FI_FRDIALOG:
        case M2FI_FRNACK: {
            // Reset routing template
            m2np.rt.hop_code    = 0;
            m2np.rt.hop_ext     = 0;
            m2np.rt.orig.value  = NULL;
            m2np.rt.dest.value  = NULL;
            
            /// Unicast and Anycast Requests have a routing template
            /// (Not currently supported, so just move the cursor ahead)
            if ((m2np.header.addr_ctl & 0x40) == 0) {
                m2np.rt.hop_code    = q_readbyte(&rxq);
                m2np.rt.orig.length = ((m2np.rt.hop_code & M2HC_VID) != 0) ? 2 : 8;                       
                m2np.rt.dest.length = m2np.rt.orig.length;
                
                if ((m2np.rt.hop_code & M2HC_EXT) != 0) {
                    m2np.rt.hop_ext = q_readbyte(&rxq);
                }
                if ((m2np.rt.hop_code & M2HC_ORIG) != 0) {
                    m2np.rt.orig.value = q_markbyte(&rxq, m2np.rt.orig.length);
                }
                if ((m2np.rt.hop_code & M2HC_DEST) != 0) {
                    m2np.rt.dest.value = q_markbyte(&rxq, m2np.rt.dest.length);
                }
            }
        } // Note case fall-through
    
        case M2FI_STREAM: {
            /// M2DP gets parsed just like M2NP, but it uses the Network data
        	/// stored from the last M2NP frame
            route_val = m2qp_parse_frame(session);
            break;
        }
        
        case M2FI_RFU: break;
    }
    
    /// Attach footer to response, if necessary
    if (route_val >= 0) {
        m2np_footer(session);
    }

#   if (OT_FEATURE(M2NP_CALLBACKS) == ENABLED) && \
        !defined(EXTF_network_sig_route)
        m2np.signal.route(route_val, session->protocol);
#   elif defined(EXTF_network_sig_route)
        network_sig_route(route_val, session->protocol);
#   endif
    
    return route_val;
}
示例#17
0
OT_WEAK void alp_breakdown_isfcomp_tmpl(ot_queue* in_q, void* data_type) {
    ((isfcomp_tmpl*)data_type)->is_series   = q_readbyte(in_q);
    ((isfcomp_tmpl*)data_type)->isf_id      = q_readbyte(in_q);
    ((isfcomp_tmpl*)data_type)->offset      = q_readshort(in_q);
}