summaryrefslogtreecommitdiff
path: root/pjlib-util
diff options
context:
space:
mode:
authorLiong Sauw Ming <ming@teluu.com>2011-10-24 09:28:13 +0000
committerLiong Sauw Ming <ming@teluu.com>2011-10-24 09:28:13 +0000
commit2068f13bc42cf3a47374aa2765f82724a5782028 (patch)
tree29fbeaa152ab51e59b650c0d7cd83a38111e1ecc /pjlib-util
parent1c72a42676e7aa0c2ae0734549050f738f3bdf02 (diff)
Re #1395: Backport of PJSIP 1.x branch into PJSIP 2.0 trunk
* Backport of r3557:r3832 TODO: ticket #1268 (Option for automatic/manual sending of RTCP SDES/BYE for the stream) for video stream. git-svn-id: http://svn.pjsip.org/repos/pjproject/trunk@3841 74dad513-b988-da41-8d7b-12977e46ad98
Diffstat (limited to 'pjlib-util')
-rw-r--r--pjlib-util/include/pjlib-util/http_client.h30
-rw-r--r--pjlib-util/src/pjlib-util/http_client.c61
-rw-r--r--pjlib-util/src/pjlib-util/pcap.c14
3 files changed, 95 insertions, 10 deletions
diff --git a/pjlib-util/include/pjlib-util/http_client.h b/pjlib-util/include/pjlib-util/http_client.h
index e2490e4c..b75c7ea8 100644
--- a/pjlib-util/include/pjlib-util/http_client.h
+++ b/pjlib-util/include/pjlib-util/http_client.h
@@ -188,6 +188,36 @@ typedef struct pj_http_req_param
*/
pj_http_auth_cred auth_cred;
+ /**
+ * Optional source port range to use when binding the socket.
+ * This can be used if the source port needs to be within a certain range
+ * for instance due to strict firewall settings. The port used will be
+ * randomized within the range.
+ *
+ * Note that if authentication is configured, the authentication response
+ * will be a new transaction
+ *
+ * Default is 0 (The OS will select the source port automatically)
+ */
+ pj_uint16_t source_port_range_start;
+
+ /**
+ * Optional source port range to use when binding.
+ * The size of the port restriction range
+ *
+ * Default is 0 (The OS will select the source port automatically))
+ */
+ pj_uint16_t source_port_range_size;
+
+ /**
+ * Max number of retries if binding to a port fails.
+ * Note that this does not adress the scenario where a request times out
+ * or errors. This needs to be taken care of by the on_complete callback.
+ *
+ * Default is 3
+ */
+ pj_uint16_t max_retries;
+
} pj_http_req_param;
/**
diff --git a/pjlib-util/src/pjlib-util/http_client.c b/pjlib-util/src/pjlib-util/http_client.c
index d455cc20..cf96a2df 100644
--- a/pjlib-util/src/pjlib-util/http_client.c
+++ b/pjlib-util/src/pjlib-util/http_client.c
@@ -26,15 +26,17 @@
#include <pj/pool.h>
#include <pj/string.h>
#include <pj/timer.h>
+#include <pj/rand.h>
#include <pjlib-util/base64.h>
#include <pjlib-util/errno.h>
#include <pjlib-util/md5.h>
#include <pjlib-util/scanner.h>
#include <pjlib-util/string.h>
+#define THIS_FILE "http_client.c"
+
#if 0
/* Enable some tracing */
- #define THIS_FILE "http_client.c"
#define TRACE_(arg) PJ_LOG(3,arg)
#else
#define TRACE_(arg)
@@ -764,6 +766,7 @@ PJ_DEF(void) pj_http_req_param_default(pj_http_req_param *param)
pj_strset2(&param->version, (char*)HTTP_1_0);
param->timeout.msec = PJ_HTTP_DEFAULT_TIMEOUT;
pj_time_val_normalize(&param->timeout);
+ param->max_retries = 3;
}
/* Get the location of '@' character to indicate the end of
@@ -1004,11 +1007,13 @@ PJ_DEF(void*) pj_http_req_get_user_data(pj_http_req *http_req)
return http_req->param.user_data;
}
-PJ_DEF(pj_status_t) pj_http_req_start(pj_http_req *http_req)
+static pj_status_t start_http_req(pj_http_req *http_req,
+ pj_bool_t notify_on_fail)
{
pj_sock_t sock = PJ_INVALID_SOCKET;
pj_status_t status;
pj_activesock_cb asock_cb;
+ int retry = 0;
PJ_ASSERT_RETURN(http_req, PJ_EINVAL);
/* Http request is not idle, a request was initiated before and
@@ -1031,7 +1036,7 @@ PJ_DEF(pj_status_t) pj_http_req_start(pj_http_req *http_req)
(http_req->param.addr_family==pj_AF_INET() &&
http_req->addr.ipv4.sin_addr.s_addr==PJ_INADDR_NONE))
{
- return status; // cannot resolve host name
+ goto on_return;
}
http_req->resolved = PJ_TRUE;
}
@@ -1045,6 +1050,32 @@ PJ_DEF(pj_status_t) pj_http_req_start(pj_http_req *http_req)
asock_cb.on_data_read = &http_on_data_read;
asock_cb.on_data_sent = &http_on_data_sent;
asock_cb.on_connect_complete = &http_on_connect;
+
+ do
+ {
+ pj_sockaddr_in bound_addr;
+ pj_uint16_t port = 0;
+
+ /* If we are using port restriction.
+ * Get a random port within the range
+ */
+ if (http_req->param.source_port_range_start != 0) {
+ port = (pj_uint16_t)
+ (http_req->param.source_port_range_start +
+ (pj_rand() % http_req->param.source_port_range_size));
+ }
+
+ pj_sockaddr_in_init(&bound_addr, NULL, port);
+ status = pj_sock_bind(sock, &bound_addr, sizeof(bound_addr));
+
+ } while (status != PJ_SUCCESS && (retry++ < http_req->param.max_retries));
+
+ if (status != PJ_SUCCESS) {
+ PJ_PERROR(1,(THIS_FILE, status,
+ "Unable to bind to the requested port"));
+ pj_sock_close(sock);
+ goto on_return;
+ }
// TODO: should we set whole data to 0 by default?
// or add it in the param?
@@ -1052,8 +1083,7 @@ PJ_DEF(pj_status_t) pj_http_req_start(pj_http_req *http_req)
NULL, http_req->ioqueue,
&asock_cb, http_req, &http_req->asock);
if (status != PJ_SUCCESS) {
- if (sock != PJ_INVALID_SOCKET)
- pj_sock_close(sock);
+ pj_sock_close(sock);
goto on_return; // error creating activesock
}
@@ -1074,7 +1104,9 @@ PJ_DEF(pj_status_t) pj_http_req_start(pj_http_req *http_req)
pj_sockaddr_get_len(&http_req->addr));
if (status == PJ_SUCCESS) {
http_req->state = SENDING_REQUEST;
- return http_req_start_sending(http_req);
+ status = http_req_start_sending(http_req);
+ if (status != PJ_SUCCESS)
+ goto on_return;
} else if (status != PJ_EPENDING) {
goto on_return; // error connecting
}
@@ -1082,10 +1114,21 @@ PJ_DEF(pj_status_t) pj_http_req_start(pj_http_req *http_req)
return PJ_SUCCESS;
on_return:
- http_req_end_request(http_req);
+ http_req->error = status;
+ if (notify_on_fail)
+ pj_http_req_cancel(http_req, PJ_TRUE);
+ else
+ http_req_end_request(http_req);
+
return status;
}
+/* Starts an asynchronous HTTP request to the URL specified. */
+PJ_DEF(pj_status_t) pj_http_req_start(pj_http_req *http_req)
+{
+ return start_http_req(http_req, PJ_FALSE);
+}
+
/* Respond to basic authentication challenge */
static pj_status_t auth_respond_basic(pj_http_req *hreq)
{
@@ -1345,7 +1388,7 @@ static pj_status_t auth_respond_digest(pj_http_req *hreq)
*/
const pj_str_t STR_MD5 = { "MD5", 3 };
const pj_str_t qop = pj_str("auth");
- const pj_str_t nc = pj_str("1");
+ const pj_str_t nc = pj_str("00000001");
const pj_str_t cnonce = pj_str("b39971");
auth_create_digest_response(&digest_response, cred,
@@ -1433,7 +1476,7 @@ static void restart_req_with_auth(pj_http_req *hreq)
http_req_end_request(hreq);
- status = pj_http_req_start(hreq);
+ status = start_http_req(hreq, PJ_TRUE);
if (status != PJ_SUCCESS)
goto on_error;
diff --git a/pjlib-util/src/pjlib-util/pcap.c b/pjlib-util/src/pjlib-util/pcap.c
index e0a86fa8..bf45b714 100644
--- a/pjlib-util/src/pjlib-util/pcap.c
+++ b/pjlib-util/src/pjlib-util/pcap.c
@@ -368,8 +368,20 @@ PJ_DEF(pj_status_t) pj_pcap_read_udp(pj_pcap_file *file,
*udp_payload_size = sz;
+ // Some layers may have trailer, e.g: link eth2.
/* Check that we've read all the packets */
- PJ_ASSERT_RETURN(sz_read == rec_incl, PJ_EBUG);
+ //PJ_ASSERT_RETURN(sz_read == rec_incl, PJ_EBUG);
+
+ /* Skip trailer */
+ while (sz_read < rec_incl) {
+ sz = rec_incl - sz_read;
+ status = read_file(file, &tmp.eth, &sz);
+ if (status != PJ_SUCCESS) {
+ TRACE_((file->obj_name, "Error reading trailer: %d", status));
+ return status;
+ }
+ sz_read += sz;
+ }
return PJ_SUCCESS;
}