summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenny Prijono <bennylp@teluu.com>2006-07-18 00:10:53 +0000
committerBenny Prijono <bennylp@teluu.com>2006-07-18 00:10:53 +0000
commitcbb6c140cf6e47e65b31b93009cfe39916933009 (patch)
treec2ba2535b30e6ea3305f3089460ca0ad3bbaf6e7
parent9c4046342c5cfb8e870d82072d52fec51eb040d5 (diff)
Fixed several bugs related to TCP:
git-svn-id: http://svn.pjsip.org/repos/pjproject/trunk@610 74dad513-b988-da41-8d7b-12977e46ad98
-rw-r--r--pjlib/include/pj/compat/os_win32.h2
-rw-r--r--pjlib/src/pj/ioqueue_common_abs.c20
-rw-r--r--pjsip/src/pjsip/sip_endpoint.c15
-rw-r--r--pjsip/src/pjsip/sip_transaction.c10
-rw-r--r--pjsip/src/pjsip/sip_transport_tcp.c32
5 files changed, 64 insertions, 15 deletions
diff --git a/pjlib/include/pj/compat/os_win32.h b/pjlib/include/pj/compat/os_win32.h
index cf7431d6..95d3cd6e 100644
--- a/pjlib/include/pj/compat/os_win32.h
+++ b/pjlib/include/pj/compat/os_win32.h
@@ -73,7 +73,7 @@
/* When this macro is set, getsockopt(SOL_SOCKET, SO_ERROR) will return
* the status of non-blocking connect() operation.
*/
-#define PJ_HAS_SO_ERROR 0
+#define PJ_HAS_SO_ERROR 1
/* This value specifies the value set in errno by the OS when a non-blocking
* socket recv() or send() can not return immediately.
diff --git a/pjlib/src/pj/ioqueue_common_abs.c b/pjlib/src/pj/ioqueue_common_abs.c
index 982c8080..5356f91d 100644
--- a/pjlib/src/pj/ioqueue_common_abs.c
+++ b/pjlib/src/pj/ioqueue_common_abs.c
@@ -209,8 +209,8 @@ void ioqueue_dispatch_write_event(pj_ioqueue_t *ioqueue, pj_ioqueue_key_t *h)
{
int value;
socklen_t vallen = sizeof(value);
- int gs_rc = getsockopt(h->fd, SOL_SOCKET, SO_ERROR,
- &value, &vallen);
+ int gs_rc = pj_sock_getsockopt(h->fd, SOL_SOCKET, SO_ERROR,
+ &value, &vallen);
if (gs_rc != 0) {
/* Argh!! What to do now???
* Just indicate that the socket is connected. The
@@ -524,8 +524,20 @@ void ioqueue_dispatch_exception_event( pj_ioqueue_t *ioqueue,
pj_mutex_unlock(h->mutex);
/* Call callback. */
- if (h->cb.on_connect_complete && !IS_CLOSING(h))
- (*h->cb.on_connect_complete)(h, -1);
+ if (h->cb.on_connect_complete && !IS_CLOSING(h)) {
+ pj_status_t status = -1;
+#if (defined(PJ_HAS_SO_ERROR) && PJ_HAS_SO_ERROR!=0)
+ int value;
+ socklen_t vallen = sizeof(value);
+ int gs_rc = pj_sock_getsockopt(h->fd, SOL_SOCKET, SO_ERROR,
+ &value, &vallen);
+ if (gs_rc == 0) {
+ status = PJ_RETURN_OS_ERROR(value);
+ }
+#endif
+
+ (*h->cb.on_connect_complete)(h, status);
+ }
}
/*
diff --git a/pjsip/src/pjsip/sip_endpoint.c b/pjsip/src/pjsip/sip_endpoint.c
index a00c1af7..aedab9d7 100644
--- a/pjsip/src/pjsip/sip_endpoint.c
+++ b/pjsip/src/pjsip/sip_endpoint.c
@@ -282,6 +282,15 @@ PJ_DEF(pj_status_t) pjsip_endpt_unregister_module( pjsip_endpoint *endpt,
on_return:
pj_rwmutex_unlock_write(endpt->mod_mutex);
+
+ if (status != PJ_SUCCESS) {
+ char errmsg[PJ_ERR_MSG_SIZE];
+
+ pj_strerror(status, errmsg, sizeof(errmsg));
+ PJ_LOG(3,(THIS_FILE, "Module \"%.*s\" can not be unregistered: %s",
+ (int)mod->name.slen, mod->name.ptr, errmsg));
+ }
+
return status;
}
@@ -526,8 +535,11 @@ PJ_DEF(void) pjsip_endpt_destroy(pjsip_endpoint *endpt)
PJ_LOG(5, (THIS_FILE, "Destroying endpoing instance.."));
/* Unregister modules. */
- while ((mod=endpt->module_list.prev) != &endpt->module_list) {
+ mod = endpt->module_list.prev;
+ while (mod != &endpt->module_list) {
+ pjsip_module *prev = mod->prev;
pjsip_endpt_unregister_module(endpt, mod);
+ mod = prev;
}
/* Shutdown and destroy all transports. */
@@ -595,6 +607,7 @@ PJ_DEF(void) pjsip_endpt_release_pool( pjsip_endpoint *endpt, pj_pool_t *pool )
*/
pj_pool_release( pool );
+ PJ_UNUSED_ARG(endpt);
/*
pj_mutex_unlock(endpt->mutex);
*/
diff --git a/pjsip/src/pjsip/sip_transaction.c b/pjsip/src/pjsip/sip_transaction.c
index 17e3ad15..6f714f2a 100644
--- a/pjsip/src/pjsip/sip_transaction.c
+++ b/pjsip/src/pjsip/sip_transaction.c
@@ -648,6 +648,15 @@ static pj_status_t mod_tsx_layer_stop(void)
*/
static pj_status_t mod_tsx_layer_unload(void)
{
+ /* Only self destroy when there's no transaction in the table.
+ * Transaction may refuse to destroy when it has pending
+ * transmission. If we destroy the module now, application will
+ * crash when the pending transaction finally got error response
+ * from transport and when it tries to unregister itself.
+ */
+ if (pj_hash_count(mod_tsx_layer.htable) != 0)
+ return PJ_EBUSY;
+
/* Destroy mutex. */
pj_mutex_destroy(mod_tsx_layer.mutex);
@@ -927,6 +936,7 @@ static void tsx_destroy( pjsip_transaction *tsx )
/* Refuse to destroy transaction if it has pending resolving. */
if (tsx->transport_flag & TSX_HAS_PENDING_TRANSPORT) {
tsx->transport_flag |= TSX_HAS_PENDING_DESTROY;
+ tsx->tsx_user = NULL;
PJ_LOG(4,(tsx->obj_name, "Will destroy later because transport is "
"in progress"));
return;
diff --git a/pjsip/src/pjsip/sip_transport_tcp.c b/pjsip/src/pjsip/sip_transport_tcp.c
index dc384d10..c9b92ad4 100644
--- a/pjsip/src/pjsip/sip_transport_tcp.c
+++ b/pjsip/src/pjsip/sip_transport_tcp.c
@@ -1240,15 +1240,6 @@ static void on_connect_complete(pj_ioqueue_key_t *key,
tcp = pj_ioqueue_get_user_data(key);
- PJ_LOG(4,(tcp->base.obj_name,
- "TCP transport %.*s:%d is connected to %.*s:%d",
- (int)tcp->base.local_name.host.slen,
- tcp->base.local_name.host.ptr,
- tcp->base.local_name.port,
- (int)tcp->base.remote_name.host.slen,
- tcp->base.remote_name.host.ptr,
- tcp->base.remote_name.port));
-
/* Mark that pending connect() operation has completed. */
tcp->has_pending_connect = PJ_FALSE;
@@ -1257,6 +1248,19 @@ static void on_connect_complete(pj_ioqueue_key_t *key,
tcp_perror(tcp->base.obj_name, "TCP connect() error", status);
+ /* Cancel all delayed transmits */
+ while (!pj_list_empty(&tcp->delayed_list)) {
+ struct delayed_tdata *pending_tx;
+ pj_ioqueue_op_key_t *op_key;
+
+ pending_tx = tcp->delayed_list.next;
+ pj_list_erase(pending_tx);
+
+ op_key = (pj_ioqueue_op_key_t*)pending_tx->tdata_op_key;
+
+ on_write_complete(tcp->key, op_key, -status);
+ }
+
/* We can not destroy the transport since high level objects may
* still keep reference to this transport. So we can only
* instruct transport manager to gracefully start the shutdown
@@ -1267,6 +1271,16 @@ static void on_connect_complete(pj_ioqueue_key_t *key,
return;
}
+ PJ_LOG(4,(tcp->base.obj_name,
+ "TCP transport %.*s:%d is connected to %.*s:%d",
+ (int)tcp->base.local_name.host.slen,
+ tcp->base.local_name.host.ptr,
+ tcp->base.local_name.port,
+ (int)tcp->base.remote_name.host.slen,
+ tcp->base.remote_name.host.ptr,
+ tcp->base.remote_name.port));
+
+
/* Update (again) local address, just in case local address currently
* set is different now that the socket is connected (could happen
* on some systems, like old Win32 probably?).