Ignore:
Timestamp:
Oct 11, 2011 4:37:37 AM (13 years ago)
Author:
bennylp
Message:

Fixed #1384: HTTP client source port range setting (thanks Johan Lantz for the patch)

Location:
pjproject/branches/1.x/pjlib-util
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • pjproject/branches/1.x/pjlib-util/include/pjlib-util/http_client.h

    r3553 r3810  
    189189    pj_http_auth_cred   auth_cred; 
    190190 
     191    /** 
     192     * Optional source port range to use when binding the socket. 
     193     * This can be used if the source port needs to be within a certain range 
     194     * for instance due to strict firewall settings. The port used will be 
     195     * randomized within the range. 
     196     * 
     197     * Note that if authentication is configured, the authentication response 
     198     * will be a new transaction 
     199     * 
     200     * Default is 0 (The OS will select the source port automatically) 
     201     */ 
     202    pj_uint16_t         source_port_range_start; 
     203 
     204    /** 
     205     * Optional source port range to use when binding. 
     206     * The size of the port restriction range 
     207     * 
     208     * Default is 0 (The OS will select the source port automatically)) 
     209     */ 
     210    pj_uint16_t         source_port_range_size; 
     211 
     212    /** 
     213     * Max number of retries if binding to a port fails. 
     214     * Note that this does not adress the scenario where a request times out 
     215     * or errors. This needs to be taken care of by the on_complete callback. 
     216     * 
     217     * Default is 3 
     218     */ 
     219    pj_uint16_t         max_retries; 
     220 
    191221} pj_http_req_param; 
    192222 
  • pjproject/branches/1.x/pjlib-util/src/pjlib-util/http_client.c

    r3600 r3810  
    2727#include <pj/string.h> 
    2828#include <pj/timer.h> 
     29#include <pj/rand.h> 
    2930#include <pjlib-util/base64.h> 
    3031#include <pjlib-util/errno.h> 
     
    3334#include <pjlib-util/string.h> 
    3435 
     36#define THIS_FILE   "http_client.c" 
     37 
    3538#if 0 
    3639    /* Enable some tracing */ 
    37     #define THIS_FILE   "http_client.c" 
    3840    #define TRACE_(arg) PJ_LOG(3,arg) 
    3941#else 
     
    765767    param->timeout.msec = PJ_HTTP_DEFAULT_TIMEOUT; 
    766768    pj_time_val_normalize(&param->timeout); 
     769    param->max_retries = 3; 
    767770} 
    768771 
     
    10051008} 
    10061009 
    1007 PJ_DEF(pj_status_t) pj_http_req_start(pj_http_req *http_req) 
     1010static pj_status_t start_http_req(pj_http_req *http_req, 
     1011                                  pj_bool_t notify_on_fail) 
    10081012{ 
    10091013    pj_sock_t sock = PJ_INVALID_SOCKET; 
    10101014    pj_status_t status; 
    10111015    pj_activesock_cb asock_cb; 
     1016    int retry = 0; 
    10121017 
    10131018    PJ_ASSERT_RETURN(http_req, PJ_EINVAL); 
     
    10321037             http_req->addr.ipv4.sin_addr.s_addr==PJ_INADDR_NONE)) 
    10331038        { 
    1034             return status; // cannot resolve host name 
     1039            goto on_return; 
    10351040        } 
    10361041        http_req->resolved = PJ_TRUE; 
     
    10461051    asock_cb.on_data_sent = &http_on_data_sent; 
    10471052    asock_cb.on_connect_complete = &http_on_connect; 
     1053         
     1054    do 
     1055    { 
     1056        pj_sockaddr_in bound_addr; 
     1057        pj_uint16_t port = 0; 
     1058 
     1059        /* If we are using port restriction. 
     1060         * Get a random port within the range 
     1061         */ 
     1062        if (http_req->param.source_port_range_start != 0) { 
     1063            port = (pj_uint16_t) 
     1064                   (http_req->param.source_port_range_start + 
     1065                    (pj_rand() % http_req->param.source_port_range_size)); 
     1066        } 
     1067 
     1068        pj_sockaddr_in_init(&bound_addr, NULL, port); 
     1069        status = pj_sock_bind(sock, &bound_addr, sizeof(bound_addr)); 
     1070 
     1071    } while (status != PJ_SUCCESS && (retry++ < http_req->param.max_retries)); 
     1072 
     1073    if (status != PJ_SUCCESS) { 
     1074        PJ_PERROR(1,(THIS_FILE, status, 
     1075                     "Unable to bind to the requested port")); 
     1076        goto on_return; 
     1077    } 
    10481078 
    10491079    // TODO: should we set whole data to 0 by default? 
     
    10751105    if (status == PJ_SUCCESS) { 
    10761106        http_req->state = SENDING_REQUEST; 
    1077         return http_req_start_sending(http_req); 
     1107        status =  http_req_start_sending(http_req); 
     1108        if (status != PJ_SUCCESS) 
     1109            goto on_return; 
    10781110    } else if (status != PJ_EPENDING) { 
    10791111        goto on_return; // error connecting 
     
    10831115 
    10841116on_return: 
    1085     http_req_end_request(http_req); 
     1117    http_req->error = status; 
     1118    if (notify_on_fail) 
     1119        pj_http_req_cancel(http_req, PJ_TRUE); 
     1120    else 
     1121        http_req_end_request(http_req); 
     1122 
    10861123    return status; 
     1124} 
     1125 
     1126/* Starts an asynchronous HTTP request to the URL specified. */ 
     1127PJ_DEF(pj_status_t) pj_http_req_start(pj_http_req *http_req) 
     1128{ 
     1129    return start_http_req(http_req, PJ_FALSE); 
    10871130} 
    10881131 
     
    14341477    http_req_end_request(hreq); 
    14351478 
    1436     status = pj_http_req_start(hreq); 
     1479    status = start_http_req(hreq, PJ_TRUE); 
    14371480    if (status != PJ_SUCCESS) 
    14381481        goto on_error; 
Note: See TracChangeset for help on using the changeset viewer.