示例#1
0
文件: sip.c 项目: rixed/junkie
static int sip_extract_content_length(unsigned unused_ field, struct liner *liner, void *info_)
{
    struct sip_proto_info *info = info_;
    info->set_values |= SIP_LENGTH_SET;
    info->content_length = liner_strtoull(liner, NULL, 10);
    return 0;
}
示例#2
0
文件: sip.c 项目: rixed/junkie
static int sip_extract_cseq(unsigned unused_ cmd, struct liner *liner, void *info_)
{
    struct sip_proto_info *info = info_;
    info->cseq = liner_strtoull(liner, NULL, 10);
    info->set_values |= SIP_CSEQ_SET;
    return 0;
}
示例#3
0
文件: sip.c 项目: rixed/junkie
static int sip_set_response(unsigned unused_ cmd, struct liner *liner, void *info_)
{
    struct sip_proto_info *info = info_;
    info->set_values |= SIP_CODE_SET;
    info->code = liner_strtoull(liner, NULL, 10);
    return 0;
}
示例#4
0
文件: sip.c 项目: rixed/junkie
static int sip_extract_via(unsigned unused_ field, struct liner *liner, void *info_)
{
    struct sip_proto_info *info = info_;

    // We are interrested only in the first Via stanza
    if (info->set_values & SIP_VIA_SET) return 0;

    // We are parsing something like : SIP/2.0/UDP 123.456.789.123:12345;foo=bar etc
    struct liner spacer;
    liner_init(&spacer, &delim_blanks, liner->start, liner_tok_length(liner));

    // Extract IP protocol
#   define SIP_VER "SIP/2.0/"
    if (liner_tok_length(&spacer) < strlen(SIP_VER) + 3) {
        SLOG(LOG_DEBUG, "Via token too short (%.*s)", (int)liner_tok_length(&spacer), spacer.start);
        return 0;
    }
    char const *proto_str = spacer.start + strlen(SIP_VER);
    if (0 == strncasecmp(proto_str, "UDP", 3)) {
        info->via.protocol = IPPROTO_UDP;
    } else if (0 == strncasecmp(proto_str, "TCP", 3)) {
        info->via.protocol = IPPROTO_TCP;
    } else {
        SLOG(LOG_DEBUG, "Via protocol unknown (%.*s)", 3, proto_str);
        return 0;
    }

    // Extract IP
    liner_next(&spacer);
    struct liner semicoloner;   // first get IP:port or IP
    liner_init(&semicoloner, &delim_semicolons, spacer.start, liner_tok_length(&spacer));
    struct liner coloner;   // then only IP and then port
    liner_init(&coloner, &delim_colons, semicoloner.start, liner_tok_length(&semicoloner));
    if (0 != ip_addr_ctor_from_str(&info->via.addr, coloner.start, liner_tok_length(&coloner), 4)) {    // FIXME: ip_addr_ctor_from_str should detect IP version
        SLOG(LOG_DEBUG, "Cannot extract IP addr from Via string (%.*s)",
            (int)liner_tok_length(&coloner), coloner.start);
        return 0;
    }

    // Extract Port
    liner_next(&coloner);
    if (liner_eof(&coloner)) {   // no port specified
        SLOG(LOG_DEBUG, "No port specified in Via string, assuming "STRIZE(SIP_PORT));
        info->via.port = SIP_PORT;
    } else {    // port is present
        char const *end;
        info->via.port = liner_strtoull(&coloner, &end, 10);
        if (end == coloner.start) {
            SLOG(LOG_DEBUG, "Cannot extract IP port from Via string (%.*s)",
                (int)liner_tok_length(&coloner), coloner.start);
            return 0;
        }
    }

    info->set_values |= SIP_VIA_SET;
    return 0;
}
示例#5
0
文件: sdp.c 项目: krissg/junkie
static int sdp_extract_port(unsigned unused_ cmd, struct liner *liner, void *info_)
{
    struct sdp_proto_info *info = info_;

    // In case several medias are advertised, we are interrested only in the first one.
    // FIXME: parse all m= stenzas with their respective attributes (a=).
    if (info->set_values & SDP_PORT_SET) return 0;

    // skip the media format ("audio", ...)
    struct liner space_liner;

    liner_init(&space_liner, &delim_spaces, (char const *)liner->start, liner_tok_length(liner));
    liner_next(&space_liner);

    char const *end;
    info->port = liner_strtoull(&space_liner, &end, 10);
    if (!info->port) // unable to extract an integer value
        return -1;

    info->set_values |= SDP_PORT_SET;
    SLOG(LOG_DEBUG, "port found (%"PRIu16")", info->port);
    return 0;
}
示例#6
0
文件: mgcp.c 项目: rixed/junkie
// FIXME: give wire_len to liner ??
static enum proto_parse_status mgcp_parse(struct parser *parser, struct proto_info *parent, unsigned way, uint8_t const *packet, size_t cap_len, size_t unused_ wire_len, struct timeval const *now, size_t tot_cap_len, uint8_t const *tot_packet)
{
    struct mgcp_parser *mgcp_parser = DOWNCAST(parser, parser, mgcp_parser);

    size_t payload = 0;
    // Parse one message (in case of piggybacking, will call ourself recursively so that subscribers are called once for each msg)
    struct mgcp_proto_info info;

    struct liner liner;
    liner_init(&liner, &delim_lines, (char const *)packet, cap_len);

    // Parse command, which is either verb + seq + endpoint + version or code + seq + blabla
    struct liner tokenizer;
    liner_init(&tokenizer, &delim_blanks, liner.start, liner_tok_length(&liner));
    if (liner_tok_length(&tokenizer) == 3 && isdigit(tokenizer.start[0])) {
        // Response
        info.response = true;
        info.u.resp.code = liner_strtoull(&tokenizer, NULL, 10);
        liner_next(&tokenizer);
        if (liner_eof(&tokenizer)) {
            SLOG(LOG_DEBUG, "Cannot parse MGCP response: missing TXID");
            return PROTO_PARSE_ERR;
        }
        info.u.resp.txid = liner_strtoull(&tokenizer, NULL, 10);
    } else {
        // Request
        info.response = false;
        info.u.query.command = mgcp_code_2_command(tokenizer.start, liner_tok_length(&tokenizer));
        if ((int)info.u.query.command == -1) return PROTO_PARSE_ERR;
        liner_next(&tokenizer);
        if (liner_eof(&tokenizer)) {
            SLOG(LOG_DEBUG, "Cannot parse MGCP query: missing TXID");
            return PROTO_PARSE_ERR;
        }
        info.u.resp.txid = liner_strtoull(&tokenizer, NULL, 10);
        liner_next(&tokenizer);
        if (liner_eof(&tokenizer)) {
            SLOG(LOG_DEBUG, "Cannot parse MGCP query: missing endpoint");
            return PROTO_PARSE_ERR;
        }
        copy_token(info.u.query.endpoint, sizeof(info.u.query.endpoint), &tokenizer);
    }
    liner_next(&liner);

    // Parse parameters up to end of msg or single dot
    struct parser *child = NULL;
    info.dialed[0] = '\0';
    info.cnx_id[0] = '\0';
    info.call_id[0] = '\0';
    info.observed = info.signaled = 0;

    while (! liner_eof(&liner)) {
        liner_init(&tokenizer, &delim_blanks, liner.start, liner_tok_length(&liner));
        liner_next(&liner);
        if (liner_tok_length(&tokenizer) == 0) {    // we met an empty line, assume following msg is SDP
            if (! mgcp_parser->sdp_parser) {
                mgcp_parser->sdp_parser = proto_sdp->ops->parser_new(proto_sdp);
            }
            child = mgcp_parser->sdp_parser;
            break;
        } else if (liner_tok_length(&tokenizer) == 1 && tokenizer.start[0] == '.') {
            break;
        } else if (liner_tok_length(&tokenizer) == 2 && tokenizer.start[1] == ':') {
            char p = tokenizer.start[0];
            liner_next(&tokenizer);
            if (liner_eof(&tokenizer)) {
                SLOG(LOG_DEBUG, "Cannot parse MGCP parameter '%c'", p);
                return PROTO_PARSE_ERR;
            }
            liner_expand(&tokenizer);
            SLOG(LOG_DEBUG, "parameter '%c'", p);
            switch (p) {
                case 'O':   // ObservedEvents: we are looking for dialed numbers or other interresting events
                    parse_observed_event(&info, &tokenizer);
                    break;
                case 'S':
                    parse_signal_request(&info, &tokenizer);
                    break;
                case 'I':
                    parse_connection_id(&info, &tokenizer);
                    break;
                case 'C':
                    parse_call_id(&info, &tokenizer);
                    break;
            }
        }
    }

    // End of message
    const size_t tot_len = liner.start - (char const *)packet;
    mgcp_proto_info_ctor(&info, parser, parent, tot_len - payload, payload);

    if (child) {
        // TODO: We suppose a call is unique in the socket pair, ie. that this parser will handle only one call, so we can keep our SDP with us.
        // SO, create a mgcp_parser with an embedded sdp parser, created as soon as mgcp_parser is constructed.
        size_t const rem_len = liner_rem_length(&liner);
        int err = proto_parse(child, &info.info, way, (uint8_t *)liner.start, rem_len, rem_len, now, tot_cap_len, tot_packet);
        if (err) proto_parse(NULL, &info.info, way, NULL, 0, 0, now, tot_cap_len, tot_packet);
        return PROTO_OK;
    }

    (void)proto_parse(NULL, &info.info, way, NULL, 0, 0, now, tot_cap_len, tot_packet);

    // In case of piggybacking, we may have further messages down there
    if (! liner_eof(&liner)) {
        size_t const rem_len = liner_rem_length(&liner);
        return mgcp_parse(parser, parent, way, (uint8_t *)liner.start, rem_len, rem_len, now, tot_cap_len, tot_packet);
    }

    return PROTO_OK;
}