Beispiel #1
0
PJ_DEF(pj_str_t*) pj_strrtrim( pj_str_t *str )
{
    char *end = str->ptr + str->slen;
    register char *p = end - 1;
    while (p >= str->ptr && pj_isspace(*p))
        --p;
    str->slen -= ((end - p) - 1);
    return str;
}
Beispiel #2
0
PJ_DEF(pj_str_t*) pj_strltrim( pj_str_t *str )
{
    register char *p = str->ptr;
    while (pj_isspace(*p))
        ++p;
    str->slen -= (p - str->ptr);
    str->ptr = p;
    return str;
}
Beispiel #3
0
/*
 * This function converts the Internet host address ccp from the standard
 * numbers-and-dots notation into binary data and stores it in the structure
 * that inp points to. 
 */
PJ_DEF(int) pj_inet_aton(const pj_str_t *ccp, struct pj_in_addr *addr)
{
    pj_uint32_t val;
    int base, n;
    char c;
    unsigned parts[4];
    unsigned *pp = parts;
    char cp_copy[18];
    char *cp = cp_copy;
    
    addr->s_addr = PJ_INADDR_NONE;

    if (ccp->slen > 15) return 0;

    pj_memcpy(cp, ccp->ptr, ccp->slen);
    cp[ccp->slen] = '\0';

    c = *cp;
    for (;;) {
	/*
	 * Collect number up to ``.''.
	 * Values are specified as for C:
	 * 0x=hex, 0=octal, isdigit=decimal.
	 */
	if (!pj_isdigit((int)c))
	    return (0);
	val = 0; base = 10;
	if (c == '0') {
	    c = *++cp;
	    if (c == 'x' || c == 'X')
		base = 16, c = *++cp;
	    else
		base = 8;
	}

	for (;;) {
	    if (pj_isascii((int)c) && pj_isdigit((int)c)) {
		val = (val * base) + (c - '0');
		c = *++cp;
	    } else if (base==16 && pj_isascii((int)c) && pj_isxdigit((int)c)) {
		val = (val << 4) |
		      (c + 10 - (pj_islower((int)c) ? 'a' : 'A'));
		c = *++cp;
	    } else
		break;
	}

	if (c == '.') {
	    /*
	     * Internet format:
	     *  a.b.c.d
	     *  a.b.c   (with c treated as 16 bits)
	     *  a.b	(with b treated as 24 bits)
	     */
	    if (pp >= parts + 3)
		return (0);
	    *pp++ = val;
	    c = *++cp;
	} else
	    break;
    }

    /*
     * Check for trailing characters.
     */
    if (c != '\0' && (!pj_isascii((int)c) || !pj_isspace((int)c)))
        return (0);
    /*
     * Concoct the address according to
     * the number of parts specified.
     */
    n = pp - parts + 1;
    switch (n) {
    case 0:
	return (0);	    /* initial nondigit */
    case 1:		/* a -- 32 bits */
	break;
    case 2:		/* a.b -- 8.24 bits */
	if (val > 0xffffff)
	    return (0);
	val |= parts[0] << 24;
	break;
    case 3:		/* a.b.c -- 8.8.16 bits */
	if (val > 0xffff)
	    return (0);
	val |= (parts[0] << 24) | (parts[1] << 16);
	break;
    case 4:		/* a.b.c.d -- 8.8.8.8 bits */
	if (val > 0xff)
	    return (0);
	val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8);
	break;
    }

    if (addr)
	addr->s_addr = pj_htonl(val);
    return (1);
}
Beispiel #4
0
/* Public function to parse multipart message bodies into its parts */
PJ_DEF(pjsip_msg_body*) pjsip_multipart_parse(pj_pool_t *pool,
					      char *buf, pj_size_t len,
					      const pjsip_media_type *ctype,
					      unsigned options)
{
    pj_str_t boundary, delim;
    char *curptr, *endptr;
    const pjsip_param *ctype_param;
    const pj_str_t STR_BOUNDARY = { "boundary", 8 };
    pjsip_msg_body *body = NULL;

    PJ_ASSERT_RETURN(pool && buf && len && ctype && !options, NULL);

    TRACE_((THIS_FILE, "Started parsing multipart body"));

    /* Get the boundary value in the ctype */
    boundary.ptr = NULL;
    boundary.slen = 0;
    ctype_param = pjsip_param_find(&ctype->param, &STR_BOUNDARY);
    if (ctype_param) {
	boundary = ctype_param->value;
	if (boundary.slen>2 && *boundary.ptr=='"') {
	    /* Remove quote */
	    boundary.ptr++;
	    boundary.slen -= 2;
	}
	TRACE_((THIS_FILE, "Boundary is specified: '%.*s'", (int)boundary.slen,
		boundary.ptr));
    }

    if (!boundary.slen) {
	/* Boundary not found or not specified. Try to be clever, get
	 * the boundary from the body.
	 */
	char *p=buf, *end=buf+len;

	PJ_LOG(4,(THIS_FILE, "Warning: boundary parameter not found or "
			     "not specified when parsing multipart body"));

	/* Find the first "--". This "--" must be right after a CRLF, unless
	 * it really appears at the start of the buffer.
	 */
	for (;;) {
	    while (p!=end && *p!='-') ++p;
	    if (p!=end && *(p+1)=='-' &&
		((p>buf && *(p-1)=='\n') || (p==buf)))
	    {
		p+=2;
		break;
	    } else {
		++p;
	    }
	}

	if (p==end) {
	    /* Unable to determine boundary. Maybe this is not a multipart
	     * message?
	     */
	    PJ_LOG(4,(THIS_FILE, "Error: multipart boundary not specified and"
				 " unable to calculate from the body"));
	    return NULL;
	}

	boundary.ptr = p;
	while (p!=end && !pj_isspace(*p)) ++p;
	boundary.slen = p - boundary.ptr;

	TRACE_((THIS_FILE, "Boundary is calculated: '%.*s'",
		(int)boundary.slen, boundary.ptr));
    }

    /* Build the delimiter:
     *   delimiter = "--" boundary
     */
    delim.slen = boundary.slen+2;
    delim.ptr = (char*)pj_pool_alloc(pool, (int)delim.slen);
    delim.ptr[0] = '-';
    delim.ptr[1] = '-';
    pj_memcpy(delim.ptr+2, boundary.ptr, boundary.slen);

    /* Start parsing the body, skip until the first delimiter. */
    curptr = buf;
    endptr = buf + len;
    {
	pj_str_t body;

	body.ptr = buf; body.slen = len;
	curptr = pj_strstr(&body, &delim);
	if (!curptr)
	    return NULL;
    }

    body = pjsip_multipart_create(pool, ctype, &boundary);

    for (;;) {
	char *start_body, *end_body;
	pjsip_multipart_part *part;

	/* Eat the boundary */
	curptr += delim.slen;
	if (*curptr=='-' && curptr<endptr-1 && *(curptr+1)=='-') {
	    /* Found the closing delimiter */
	    curptr += 2;
	    break;
	}
	/* Optional whitespace after delimiter */
	while (curptr!=endptr && IS_SPACE(*curptr)) ++curptr;
	/* Mandatory CRLF */
	if (*curptr=='\r') ++curptr;
	if (*curptr!='\n') {
	    /* Expecting a newline here */
	    return NULL;
	}
	++curptr;

	/* We now in the start of the body */
	start_body = curptr;

	/* Find the next delimiter */
	{
	    pj_str_t subbody;

	    subbody.ptr = curptr; subbody.slen = endptr - curptr;
	    curptr = pj_strstr(&subbody, &delim);
	    if (!curptr) {
		/* We're really expecting end delimiter to be found. */
		return NULL;
	    }
	}

	end_body = curptr;

	/* The newline preceeding the delimiter is conceptually part of
	 * the delimiter, so trim it from the body.
	 */
	if (*(end_body-1) == '\n')
	    --end_body;
	if (*(end_body-1) == '\r')
	    --end_body;

	/* Now that we have determined the part's boundary, parse it
	 * to get the header and body part of the part.
	 */
	part = parse_multipart_part(pool, start_body, end_body - start_body,
				    ctype);
	if (part) {
	    pjsip_multipart_add_part(pool, body, part);
	}
    }

    return body;
}
Beispiel #5
0
/*
 * Input and parse SDP from the remote (containing remote's ICE information) 
 * and save it to global variables.
 */
static void icedemo_input_remote(void)
{
    char linebuf[80];
    unsigned media_cnt = 0;
    unsigned comp0_port = 0;
    char     comp0_addr[80];
    pj_bool_t done = PJ_FALSE;

    puts("Paste SDP from remote host, end with empty line");

    reset_rem_info();

    comp0_addr[0] = '\0';

    while (!done) {
	int len;
	char *line;

	printf(">");
	if (stdout) fflush(stdout);

	if (fgets(linebuf, sizeof(linebuf), stdin)==NULL)
	    break;

	len = strlen(linebuf);
	while (len && (linebuf[len-1] == '\r' || linebuf[len-1] == '\n'))
	    linebuf[--len] = '\0';

	line = linebuf;
	while (len && pj_isspace(*line))
	    ++line, --len;

	if (len==0)
	    break;

	/* Ignore subsequent media descriptors */
	if (media_cnt > 1)
	    continue;

	switch (line[0]) {
	case 'm':
	    {
		int cnt;
		char media[32], portstr[32];

		++media_cnt;
		if (media_cnt > 1) {
		    puts("Media line ignored");
		    break;
		}

		cnt = sscanf(line+2, "%s %s RTP/", media, portstr);
		if (cnt != 2) {
		    PJ_LOG(1,(THIS_FILE, "Error parsing media line"));
		    goto on_error;
		}

		comp0_port = atoi(portstr);
		
	    }
	    break;
	case 'c':
	    {
		int cnt;
		char c[32], net[32], ip[80];
		
		cnt = sscanf(line+2, "%s %s %s", c, net, ip);
		if (cnt != 3) {
		    PJ_LOG(1,(THIS_FILE, "Error parsing connection line"));
		    goto on_error;
		}

		strcpy(comp0_addr, ip);
	    }
	    break;
	case 'a':
	    {
		char *attr = strtok(line+2, ": \t\r\n");
		if (strcmp(attr, "ice-ufrag")==0) {
		    strcpy(icedemo.rem.ufrag, attr+strlen(attr)+1);
		} else if (strcmp(attr, "ice-pwd")==0) {
		    strcpy(icedemo.rem.pwd, attr+strlen(attr)+1);
		} else if (strcmp(attr, "rtcp")==0) {
		    char *val = attr+strlen(attr)+1;
		    int af, cnt;
		    int port;
		    char net[32], ip[64];
		    pj_str_t tmp_addr;
		    pj_status_t status;

		    cnt = sscanf(val, "%d IN %s %s", &port, net, ip);
		    if (cnt != 3) {
			PJ_LOG(1,(THIS_FILE, "Error parsing rtcp attribute"));
			goto on_error;
		    }

		    if (strchr(ip, ':'))
			af = pj_AF_INET6();
		    else
			af = pj_AF_INET();

		    pj_sockaddr_init(af, &icedemo.rem.def_addr[1], NULL, 0);
		    tmp_addr = pj_str(ip);
		    status = pj_sockaddr_set_str_addr(af, &icedemo.rem.def_addr[1],
						      &tmp_addr);
		    if (status != PJ_SUCCESS) {
			PJ_LOG(1,(THIS_FILE, "Invalid IP address"));
			goto on_error;
		    }
		    pj_sockaddr_set_port(&icedemo.rem.def_addr[1], (pj_uint16_t)port);

		} else if (strcmp(attr, "candidate")==0) {
		    char *sdpcand = attr+strlen(attr)+1;
		    int af, cnt;
		    char foundation[32], transport[12], ipaddr[80], type[32];
		    pj_str_t tmpaddr;
		    int comp_id, prio, port;
		    pj_ice_sess_cand *cand;
		    pj_status_t status;

		    cnt = sscanf(sdpcand, "%s %d %s %d %s %d typ %s",
				 foundation,
				 &comp_id,
				 transport,
				 &prio,
				 ipaddr,
				 &port,
				 type);
		    if (cnt != 7) {
			PJ_LOG(1, (THIS_FILE, "error: Invalid ICE candidate line"));
			goto on_error;
		    }

		    cand = &icedemo.rem.cand[icedemo.rem.cand_cnt];
		    pj_bzero(cand, sizeof(*cand));
		    
		    if (strcmp(type, "host")==0)
			cand->type = PJ_ICE_CAND_TYPE_HOST;
		    else if (strcmp(type, "srflx")==0)
			cand->type = PJ_ICE_CAND_TYPE_SRFLX;
		    else if (strcmp(type, "relay")==0)
			cand->type = PJ_ICE_CAND_TYPE_RELAYED;
		    else {
			PJ_LOG(1, (THIS_FILE, "Error: invalid candidate type '%s'", 
				   type));
			goto on_error;
		    }

		    cand->comp_id = (pj_uint8_t)comp_id;
		    pj_strdup2(icedemo.pool, &cand->foundation, foundation);
		    cand->prio = prio;
		    
		    if (strchr(ipaddr, ':'))
			af = pj_AF_INET6();
		    else
			af = pj_AF_INET();

		    tmpaddr = pj_str(ipaddr);
		    pj_sockaddr_init(af, &cand->addr, NULL, 0);
		    status = pj_sockaddr_set_str_addr(af, &cand->addr, &tmpaddr);
		    if (status != PJ_SUCCESS) {
			PJ_LOG(1,(THIS_FILE, "Error: invalid IP address '%s'",
				  ipaddr));
			goto on_error;
		    }

		    pj_sockaddr_set_port(&cand->addr, (pj_uint16_t)port);

		    ++icedemo.rem.cand_cnt;

		    if (cand->comp_id > icedemo.rem.comp_cnt)
			icedemo.rem.comp_cnt = cand->comp_id;
		}
	    }
	    break;
	}
    }

    if (icedemo.rem.cand_cnt==0 ||
	icedemo.rem.ufrag[0]==0 ||
	icedemo.rem.pwd[0]==0 ||
	icedemo.rem.comp_cnt == 0)
    {
	PJ_LOG(1, (THIS_FILE, "Error: not enough info"));
	goto on_error;
    }

    if (comp0_port==0 || comp0_addr[0]=='\0') {
	PJ_LOG(1, (THIS_FILE, "Error: default address for component 0 not found"));
	goto on_error;
    } else {
	int af;
	pj_str_t tmp_addr;
	pj_status_t status;

	if (strchr(comp0_addr, ':'))
	    af = pj_AF_INET6();
	else
	    af = pj_AF_INET();

	pj_sockaddr_init(af, &icedemo.rem.def_addr[0], NULL, 0);
	tmp_addr = pj_str(comp0_addr);
	status = pj_sockaddr_set_str_addr(af, &icedemo.rem.def_addr[0],
					  &tmp_addr);
	if (status != PJ_SUCCESS) {
	    PJ_LOG(1,(THIS_FILE, "Invalid IP address in c= line"));
	    goto on_error;
	}
	pj_sockaddr_set_port(&icedemo.rem.def_addr[0], (pj_uint16_t)comp0_port);
    }

    PJ_LOG(3, (THIS_FILE, "Done, %d remote candidate(s) added", 
	       icedemo.rem.cand_cnt));
    return;

on_error:
    reset_rem_info();
}
Beispiel #6
0
/*
 * Input URL.
 */
static void ui_input_url(const char *title, char *buf, pj_size_t len,
			 input_result *result)
{
    result->nb_result = PJSUA_APP_NO_NB;
    result->uri_result = NULL;

    print_buddy_list();

    printf("Choices:\n"
	   "   0         For current dialog.\n"
	   "  -1         All %d buddies in buddy list\n"
	   "  [1 -%2d]    Select from buddy list\n"
	   "  URL        An URL\n"
	   "  <Enter>    Empty input (or 'q') to cancel\n"
	   , pjsua_get_buddy_count(), pjsua_get_buddy_count());
    printf("%s: ", title);

    fflush(stdout);
    if (fgets(buf, (int)len, stdin) == NULL)
	return;
    len = strlen(buf);

    /* Left trim */
    while (pj_isspace(*buf)) {
	++buf;
	--len;
    }

    /* Remove trailing newlines */
    while (len && (buf[len-1] == '\r' || buf[len-1] == '\n'))
	buf[--len] = '\0';

    if (len == 0 || buf[0]=='q')
	return;

    if (pj_isdigit(*buf) || *buf=='-') {

	unsigned i;

	if (*buf=='-')
	    i = 1;
	else
	    i = 0;

	for (; i<len; ++i) {
	    if (!pj_isdigit(buf[i])) {
		puts("Invalid input");
		return;
	    }
	}

	result->nb_result = my_atoi(buf);

	if (result->nb_result >= 0 &&
	    result->nb_result <= (int)pjsua_get_buddy_count())
	{
	    return;
	}
	if (result->nb_result == -1)
	    return;

	puts("Invalid input");
	result->nb_result = PJSUA_APP_NO_NB;
	return;

    } else {
	pj_status_t status;

	if ((status=pjsua_verify_url(buf)) != PJ_SUCCESS) {
	    pjsua_perror(THIS_FILE, "Invalid URL", status);
	    return;
	}

	result->uri_result = buf;
    }
}