struct ibsp_socket_info *socket_info =\r
(struct ibsp_socket_info * __ptr64)p_cm_req_rec->context;\r
struct listen_incoming *incoming;\r
- ib_rej_status_t rej_status;\r
ib_cm_mra_t mra;\r
\r
- CL_ENTER( IBSP_DBG_CM, gdbg_lvl );\r
+ IBSP_ENTER( IBSP_DBG_CM );\r
\r
CL_ASSERT( socket_info );\r
-\r
- if( !p_cm_req_rec->p_req_pdata )\r
- {\r
- CL_ERROR( IBSP_DBG_CM, gdbg_lvl, ("No private data in CM REQ\n") );\r
- rej_status = IB_REJ_INSUF_RESOURCES;\r
- CL_EXIT_ERROR( IBSP_DBG_CM, gdbg_lvl, ("rejecting\n") );\r
- ib_reject( p_cm_req_rec->h_cm_req, rej_status );\r
- return;\r
- }\r
+ CL_ASSERT( p_cm_req_rec->p_req_pdata );\r
\r
incoming = HeapAlloc( g_ibsp.heap, 0, sizeof(struct listen_incoming) );\r
- if( incoming == NULL )\r
+ if( !incoming )\r
{\r
/* Low on memory. */\r
- CL_ERROR( IBSP_DBG_CM, gdbg_lvl, ("HeapAlloc failed\n") );\r
- rej_status = IB_REJ_INSUF_RESOURCES;\r
- CL_EXIT_ERROR( IBSP_DBG_CM, gdbg_lvl, ("rejecting\n") );\r
- ib_reject( p_cm_req_rec->h_cm_req, rej_status );\r
+ IBSP_ERROR( ("HeapAlloc failed, rejecting\n") );\r
+ ib_reject( p_cm_req_rec->h_cm_req, IB_REJ_INSUF_RESOURCES );\r
+ IBSP_EXIT( IBSP_DBG_CM );\r
return;\r
}\r
\r
if( cl_qlist_count( &socket_info->info.listen.list ) >= socket_info->info.listen.backlog )\r
{\r
/* Already too many connection requests are queued */\r
- cl_spinlock_release( &socket_info->mutex );\r
- CL_ERROR( IBSP_DBG_CM, gdbg_lvl, ("already too many incoming connections\n") );\r
+ IBSP_TRACE1( IBSP_DBG_CM,\r
+ ("already too many incoming connections, rejecting\n") );\r
HeapFree( g_ibsp.heap, 0, incoming );\r
- rej_status = IB_REJ_INSUF_QP; /* or IB_REJ_INSUF_RESOURCES */\r
- CL_EXIT_ERROR( IBSP_DBG_CM, gdbg_lvl, ("rejecting\n") );\r
- ib_reject( p_cm_req_rec->h_cm_req, rej_status );\r
- return;\r
+ ib_reject( p_cm_req_rec->h_cm_req, IB_REJ_USER_DEFINED );\r
+ break;\r
}\r
\r
/* Add to the waiting list */\r
/* Send MRA */\r
mra.mra_length = 0;\r
mra.p_mra_pdata = NULL;\r
- mra.svc_timeout = 0x1F;\r
+ mra.svc_timeout = 0x15;\r
ib_cm_mra( p_cm_req_rec->h_cm_req, &mra );\r
\r
ibsp_post_select_event( socket_info, FD_ACCEPT, 0 );\r
\r
case IBSP_DUPLICATING_REMOTE:\r
{\r
- int error;\r
int ret;\r
\r
HeapFree( g_ibsp.heap, 0, incoming );\r
\r
wait_cq_drain( socket_info );\r
\r
- ib_destroy_socket( socket_info );\r
+ /* Non-blocking cancel since we're in CM callback context */\r
+ ib_cm_cancel( socket_info->info.listen.handle, NULL );\r
+ socket_info->info.listen.handle = NULL;\r
\r
#if 0\r
cl_spinlock_release( &socket_info->mutex );\r
- rej_status = IB_REJ_USER_DEFINED;\r
CL_EXIT_ERROR( IBSP_DBG_CM, gdbg_lvl, ("rejecting\n") );\r
- ib_reject( p_cm_req_rec->h_cm_req, rej_status );\r
+ ib_reject( p_cm_req_rec->h_cm_req, IB_REJ_USER_DEFINED );\r
ibsp_dup_overlap_abort( socket_info );\r
return;\r
#endif\r
\r
- ret = ib_create_socket( socket_info );\r
- if( ret )\r
- {\r
- cl_spinlock_release( &socket_info->mutex );\r
- CL_ERROR( IBSP_DBG_CM, gdbg_lvl,\r
- ("accept failed for duplicate socket (%d)\n", ret) );\r
- rej_status = IB_REJ_USER_DEFINED;\r
- CL_EXIT_ERROR( IBSP_DBG_CM, gdbg_lvl, ("rejecting\n") );\r
- ib_reject( p_cm_req_rec->h_cm_req, rej_status );\r
- ibsp_dup_overlap_abort( socket_info );\r
- return;\r
- }\r
\r
- ret = ib_accept( socket_info, p_cm_req_rec, &error );\r
+ ret = ib_accept( socket_info, p_cm_req_rec );\r
if( ret )\r
{\r
cl_spinlock_release( &socket_info->mutex );\r
- CL_ERROR( IBSP_DBG_CM, gdbg_lvl,\r
- ("accept failed for duplicate socket (%d, %d)\n", ret, error) );\r
- rej_status = IB_REJ_USER_DEFINED;\r
+ IBSP_ERROR(\r
+ ("ib_accept for duplicate socket returned %d, rejecting\n",\r
+ ret) );\r
/* Call ib_destroy_socket for above ib_create_socket() call */\r
ib_destroy_socket( socket_info );\r
- CL_EXIT_ERROR( IBSP_DBG_CM, gdbg_lvl, ("rejecting\n") );\r
- ib_reject( p_cm_req_rec->h_cm_req, rej_status );\r
+ ib_reject( p_cm_req_rec->h_cm_req, IB_REJ_USER_DEFINED );\r
ibsp_dup_overlap_abort( socket_info );\r
+ IBSP_EXIT( IBSP_DBG_CM );\r
return;\r
-\r
}\r
}\r
break;\r
\r
default:\r
- cl_spinlock_release( &socket_info->mutex );\r
- CL_ERROR( IBSP_DBG_CM, gdbg_lvl, ("socket is not listening anymore\n") );\r
+ IBSP_ERROR( ("socket is not listening anymore\n") );\r
HeapFree( g_ibsp.heap, 0, incoming );\r
- rej_status = IB_REJ_INSUF_QP; /* or IB_REJ_INSUF_RESOURCES */\r
- CL_EXIT_ERROR( IBSP_DBG_CM, gdbg_lvl, ("rejecting\n") );\r
- ib_reject( p_cm_req_rec->h_cm_req, rej_status );\r
- return;\r
+ /* We're closing down - let some other listen match. */\r
+ ib_reject( p_cm_req_rec->h_cm_req, IB_REJ_INVALID_SID );\r
+ break;\r
}\r
\r
cl_spinlock_release( &socket_info->mutex );\r
\r
- CL_EXIT( IBSP_DBG_CM, gdbg_lvl );\r
+ IBSP_EXIT( IBSP_DBG_CM );\r
}\r
\r
\r
\r
cl_spinlock_release( &socket_info->mutex );\r
\r
- CL_EXIT( IBSP_DBG_CM, gdbg_lvl );\r
+ IBSP_EXIT( IBSP_DBG_CM );\r
}\r
\r
\r
struct ibsp_socket_info *socket_info =\r
(struct ibsp_socket_info * __ptr64)p_cm_rej_rec->qp_context;\r
\r
- CL_ENTER( IBSP_DBG_CM, gdbg_lvl );\r
-\r
- fzprint(("%s():%d:0x%x:0x%x: socket=0x%p \n", __FUNCTION__,\r
- __LINE__, GetCurrentProcessId(), GetCurrentThreadId(), socket_info));\r
+ IBSP_ENTER( IBSP_DBG_CM );\r
\r
- CL_TRACE( IBSP_DBG_CONN, gdbg_lvl, ("connect reject, reason=%d\n",\r
- p_cm_rej_rec->rej_status));\r
+ IBSP_TRACE( IBSP_DBG_CONN, ("socket %p connect reject, reason=%d\n",\r
+ socket_info, cl_ntoh16(p_cm_rej_rec->rej_status)) );\r
\r
cl_spinlock_acquire( &socket_info->mutex );\r
\r
switch( socket_info->socket_state )\r
{\r
case IBSP_CONNECT:\r
+ /* Remove from connection map. */\r
+ ibsp_conn_remove( socket_info );\r
+\r
IBSP_CHANGE_SOCKET_STATE( socket_info, IBSP_BIND );\r
- ibsp_post_select_event( socket_info, FD_CONNECT, WSAECONNREFUSED );\r
+ if( p_cm_rej_rec->rej_status == IB_REJ_TIMEOUT )\r
+ ibsp_post_select_event( socket_info, FD_CONNECT, WSAETIMEDOUT );\r
+ else\r
+ ibsp_post_select_event( socket_info, FD_CONNECT, WSAECONNREFUSED );\r
break;\r
\r
case IBSP_ACCEPT:\r
+ /* Remove from connection map. */\r
+ ibsp_conn_remove( socket_info );\r
+\r
IBSP_CHANGE_SOCKET_STATE( socket_info, IBSP_BIND );\r
- SetEvent( socket_info->info.accept.event );\r
- break;\r
+ /* Fall through. */\r
\r
case IBSP_DUPLICATING_NEW:\r
/* Leave in that state. IBSPSocket will eventually return \r
break;\r
\r
default:\r
- CL_ERROR( IBSP_DBG_CM, gdbg_lvl, ("Got an unexpected REJ\n") );\r
+ IBSP_ERROR( ("socket %p got an REJ reason %d in state %s\n",\r
+ socket_info, cl_ntoh16( p_cm_rej_rec->rej_status ),\r
+ IBSP_SOCKET_STATE_STR(socket_info->socket_state)) );\r
break;\r
}\r
\r
cl_spinlock_release( &socket_info->mutex );\r
\r
- CL_EXIT( IBSP_DBG_CM, gdbg_lvl );\r
+ IBSP_EXIT( IBSP_DBG_CM );\r
}\r
\r
\r
struct ibsp_socket_info *socket_info =\r
(struct ibsp_socket_info * __ptr64)p_cm_dreq_rec->qp_context;\r
\r
- CL_ENTER( IBSP_DBG_CM, gdbg_lvl );\r
- CL_TRACE( IBSP_DBG_CM, gdbg_lvl,\r
- ("cm_dreq_callback: enter, socket_state=%s, socket=%p\n",\r
- IBSP_SOCKET_STATE_STR( socket_info->socket_state ), socket_info) );\r
+ IBSP_ENTER( IBSP_DBG_CM );\r
+ IBSP_TRACE1( IBSP_DBG_CM,\r
+ ("socket=%p state=%s\n",\r
+ socket_info, IBSP_SOCKET_STATE_STR( socket_info->socket_state )) );\r
\r
reason = (struct disconnect_reason * __ptr64)p_cm_dreq_rec->p_dreq_pdata;\r
\r
- if( reason->type == DISC_DUPLICATING )\r
- {\r
- cl_spinlock_acquire( &socket_info->mutex );\r
+ cl_spinlock_acquire( &socket_info->mutex );\r
\r
- if( socket_info->socket_state == IBSP_CONNECTED )\r
+ if( socket_info->socket_state == IBSP_CONNECTED )\r
+ {\r
+ switch( reason->type )\r
{\r
- int ret;\r
- int error;\r
-\r
- IBSP_CHANGE_SOCKET_STATE( socket_info, IBSP_DUPLICATING_REMOTE );\r
- socket_info->qp_error = -1;\r
- socket_info->duplicate.identifier = reason->duplicating.identifier;\r
- socket_info->duplicate.dwProcessId = reason->duplicating.dwProcessId;\r
-\r
- /* Now, setup our listening callback. */\r
- socket_info->info.listen.listen_req_param.dwProcessId =\r
- reason->duplicating.dwProcessId;\r
- socket_info->info.listen.listen_req_param.identifier =\r
- reason->duplicating.identifier;\r
-\r
- ret = ib_listen( socket_info, &error );\r
- if( ret )\r
+ case DISC_DUPLICATING:\r
{\r
- CL_EXIT_ERROR( IBSP_DBG_CONN, gdbg_lvl,\r
- ("ib_listen failed with %d\n", error) );\r
- IBSP_CHANGE_SOCKET_STATE( socket_info, IBSP_DISCONNECTED );\r
- socket_info->qp_error = WSAECONNRESET;\r
+ int ret;\r
+ int error;\r
+\r
+ IBSP_CHANGE_SOCKET_STATE( socket_info, IBSP_DUPLICATING_REMOTE );\r
+ socket_info->qp_error = -1;\r
+ socket_info->duplicate.identifier = reason->duplicating.identifier;\r
+ socket_info->duplicate.dwProcessId = reason->duplicating.dwProcessId;\r
+\r
+ /* Now, setup our listening callback. */\r
+ socket_info->info.listen.listen_req_param.dwProcessId =\r
+ reason->duplicating.dwProcessId;\r
+ socket_info->info.listen.listen_req_param.identifier =\r
+ reason->duplicating.identifier;\r
+\r
+ ret = ib_listen( socket_info, &error );\r
+ if( !ret )\r
+ break;\r
+\r
+ IBSP_ERROR_EXIT( ("ib_listen failed with %d\n", error) );\r
+ /* Fall through. */\r
}\r
+ default:\r
+ /* Right now, treat anything as a normal disconnect. */\r
+ IBSP_CHANGE_SOCKET_STATE( socket_info, IBSP_DISCONNECTED );\r
+ /* We changed the state - remove from connection map. */\r
+ ibsp_conn_remove( socket_info );\r
+ socket_info->qp_error = WSAECONNRESET;\r
}\r
-\r
- cl_spinlock_release( &socket_info->mutex );\r
}\r
else\r
{\r
- /* Right now, treat anything as a normal disconnect. */\r
- cl_spinlock_acquire( &socket_info->mutex );\r
-\r
- if( socket_info->socket_state == IBSP_CONNECTED )\r
- {\r
- IBSP_CHANGE_SOCKET_STATE( socket_info, IBSP_DISCONNECTED );\r
- socket_info->qp_error = WSAECONNRESET;\r
- }\r
-\r
- cl_spinlock_release( &socket_info->mutex );\r
}\r
+ cl_spinlock_release( &socket_info->mutex );\r
\r
memset( &cm_drep, 0, sizeof(cm_drep) );\r
\r
status = ib_cm_drep( p_cm_dreq_rec->h_cm_dreq, &cm_drep );\r
if( status != IB_SUCCESS )\r
- {\r
- CL_ERROR( IBSP_DBG_CM, gdbg_lvl, ("ib_cm_drep failed (0x%d)\n", status) );\r
- }\r
-\r
- SetEvent( socket_info->info.disconnect.event );\r
+ IBSP_ERROR( ("ib_cm_drep returned %s\n", ib_get_err_str( status )) );\r
\r
- CL_EXIT( IBSP_DBG_CM, gdbg_lvl );\r
+ IBSP_EXIT( IBSP_DBG_CM );\r
}\r
\r
\r
cm_drep_callback(\r
IN ib_cm_drep_rec_t *p_cm_drep_rec )\r
{\r
- struct ibsp_socket_info *socket_info =\r
- (struct ibsp_socket_info * __ptr64)p_cm_drep_rec->qp_context;\r
-\r
CL_ENTER( IBSP_DBG_CM, gdbg_lvl );\r
-\r
- CL_TRACE( IBSP_DBG_CM, gdbg_lvl, ("posting DREP event from drep_callback\n") );\r
-\r
- SetEvent( socket_info->info.disconnect.event );\r
-\r
+ UNUSED_PARAM( p_cm_drep_rec );\r
CL_EXIT( IBSP_DBG_CM, gdbg_lvl );\r
}\r
\r
\r
\r
/* Reject all the queued incoming connection requests. */\r
-static void\r
-empty_listen_queue(\r
- IN struct ibsp_socket_info *socket_info )\r
+void\r
+ib_listen_backlog(\r
+ IN struct ibsp_socket_info *socket_info,\r
+ IN int backlog )\r
{\r
cl_list_item_t *item;\r
struct listen_incoming *incoming;\r
\r
- // TODO: we don't need to lock anymore, do we?\r
- cl_spinlock_acquire( &socket_info->mutex );\r
+ socket_info->info.listen.backlog = backlog;\r
\r
- for( item = cl_qlist_head( &socket_info->info.listen.list );\r
- item != cl_qlist_end( &socket_info->info.listen.list );\r
- item = cl_qlist_head( &socket_info->info.listen.list ) )\r
+ while(\r
+ cl_qlist_count( &socket_info->info.listen.list ) > (uint32_t)backlog )\r
{\r
- incoming = PARENT_STRUCT(item, struct listen_incoming, item);\r
+ item = cl_qlist_remove_tail( &socket_info->info.listen.list );\r
\r
- cl_qlist_remove_item( &socket_info->info.listen.list, &incoming->item );\r
+ incoming = PARENT_STRUCT(item, struct listen_incoming, item);\r
\r
ib_reject( incoming->cm_req_received.h_cm_req, IB_REJ_USER_DEFINED );\r
\r
HeapFree( g_ibsp.heap, 0, incoming );\r
}\r
-\r
- cl_spinlock_release( &socket_info->mutex );\r
}\r
\r
\r
{\r
ib_api_status_t status;\r
\r
- CL_ENTER( IBSP_DBG_CM, gdbg_lvl );\r
+ IBSP_ENTER( IBSP_DBG_CM );\r
\r
/* We should be in the CLOSING state */\r
CL_ASSERT( socket_info->socket_state == IBSP_CLOSING );\r
\r
/* We can empty the queue now. Since we are closing, \r
* no new entry will be added. */\r
- empty_listen_queue( socket_info );\r
+ cl_spinlock_acquire( &socket_info->mutex );\r
+ ib_listen_backlog( socket_info, 0 );\r
+ cl_spinlock_release( &socket_info->mutex );\r
\r
socket_info->info.listen.handle = NULL;\r
\r
- CL_EXIT( IBSP_DBG_CM, gdbg_lvl );\r
+ IBSP_EXIT( IBSP_DBG_CM );\r
}\r
\r
\r
int\r
ib_connect(\r
IN struct ibsp_socket_info *socket_info,\r
- IN ib_path_rec_t *path_rec,\r
- OUT LPINT lpErrno )\r
+ IN ib_path_rec_t *path_rec )\r
{\r
ib_cm_req_t cm_req;\r
ib_api_status_t status;\r
struct cm_req_params params;\r
\r
- CL_ENTER( IBSP_DBG_CM, gdbg_lvl );\r
+ IBSP_ENTER( IBSP_DBG_CM );\r
\r
fzprint(("%s():%d:0x%x:0x%x: socket=0x%p \n", __FUNCTION__,\r
__LINE__, GetCurrentProcessId(), GetCurrentThreadId(), socket_info));\r
\r
+ CL_TRACE( IBSP_DBG_CM, gdbg_lvl, ("From:\n") );\r
+ DebugPrintSockAddr( IBSP_DBG_CM, gdbg_lvl, &socket_info->local_addr );\r
+ CL_TRACE( IBSP_DBG_CM, gdbg_lvl, ("To:\n") );\r
+ DebugPrintSockAddr( IBSP_DBG_CM, gdbg_lvl, &socket_info->peer_addr );\r
+\r
+ /* Insert into the connection map. */\r
+ if( !ibsp_conn_insert( socket_info ) )\r
+ {\r
+ IBSP_EXIT( IBSP_DBG_CM );\r
+ return WSAEADDRINUSE;\r
+ }\r
\r
memset( &cm_req, 0, sizeof(cm_req) );\r
\r
CL_TRACE( IBSP_DBG_CM, gdbg_lvl,\r
("connecting to port %d, SID=%016I64x\n", socket_info->peer_addr.sin_port,\r
cm_req.svc_id) );\r
- CL_TRACE( IBSP_DBG_CM, gdbg_lvl, ("From:\n") );\r
- DebugPrintSockAddr( IBSP_DBG_CM, gdbg_lvl, &socket_info->local_addr );\r
- CL_TRACE( IBSP_DBG_CM, gdbg_lvl, ("To:\n") );\r
- DebugPrintSockAddr( IBSP_DBG_CM, gdbg_lvl, &socket_info->peer_addr );\r
\r
cm_req.req_length = sizeof(struct cm_req_params);\r
\r
status = ib_cm_req( &cm_req );\r
if( status != IB_SUCCESS )\r
{\r
- CL_EXIT_ERROR( IBSP_DBG_CM, gdbg_lvl, ("ib_cm_req failed (0x%d)\n", status) );\r
- *lpErrno = ibal_to_wsa_error( status );\r
- return SOCKET_ERROR;\r
- }\r
+ /* Remove from connection map. */\r
+ ibsp_conn_remove( socket_info );\r
\r
- CL_EXIT( IBSP_DBG_CM, gdbg_lvl );\r
+ IBSP_ERROR_EXIT( ("ib_cm_req failed (0x%d)\n", status) );\r
+ return WSAEHOSTUNREACH;\r
+ }\r
\r
- *lpErrno = 0;\r
- return 0;\r
+ IBSP_EXIT( IBSP_DBG_CM );\r
+ /* Operation is pending */\r
+ return WSAEWOULDBLOCK;\r
}\r
\r
+\r
void\r
ib_reject(\r
IN const ib_cm_handle_t h_cm,\r
ib_cm_rej_t cm_rej;\r
ib_api_status_t status;\r
\r
- CL_ENTER( IBSP_DBG_CM, gdbg_lvl );\r
-\r
- UNUSED_PARAM( rej_status );\r
+ IBSP_ENTER( IBSP_DBG_CM );\r
\r
memset( &cm_rej, 0, sizeof(cm_rej) );\r
+ cm_rej.rej_status = rej_status;\r
\r
status = ib_cm_rej( h_cm, &cm_rej );\r
if( status != IB_SUCCESS )\r
- {\r
- CL_ERROR( IBSP_DBG_CM, gdbg_lvl, ("ib_cm_rej failed (0x%d)\n", status) );\r
- }\r
+ IBSP_ERROR( ("ib_cm_rej returned %s\n", ib_get_err_str( status )) );\r
\r
- CL_EXIT( IBSP_DBG_CM, gdbg_lvl );\r
+ IBSP_EXIT( IBSP_DBG_CM );\r
}\r
\r
\r
int\r
ib_accept(\r
IN struct ibsp_socket_info *socket_info,\r
- IN ib_cm_req_rec_t *cm_req_received,\r
- OUT LPINT lpErrno )\r
+ IN ib_cm_req_rec_t *cm_req_received )\r
{\r
ib_cm_rep_t cm_rep;\r
ib_api_status_t status;\r
\r
- CL_ENTER( IBSP_DBG_CM, gdbg_lvl );\r
+ IBSP_ENTER( IBSP_DBG_CM );\r
+\r
+ /* Insert into the connection map. */\r
+ if( !ibsp_conn_insert( socket_info ) )\r
+ {\r
+ IBSP_EXIT( IBSP_DBG_CM );\r
+ return WSAEADDRINUSE;\r
+ }\r
\r
memset( &cm_rep, 0, sizeof(cm_rep) );\r
\r
status = ib_cm_rep( cm_req_received->h_cm_req, &cm_rep );\r
if( status != IB_SUCCESS )\r
{\r
- CL_EXIT_ERROR( IBSP_DBG_CM, gdbg_lvl, ("ib_cm_rep failed (0x%d)\n", status) );\r
- *lpErrno = ibal_to_wsa_error( status );\r
- return SOCKET_ERROR;\r
- }\r
+ /* Remove from connection map. */\r
+ ibsp_conn_remove( socket_info );\r
\r
- CL_EXIT( IBSP_DBG_CM, gdbg_lvl );\r
+ IBSP_ERROR_EXIT(\r
+ ("ib_cm_rep failed (0x%d) at time %I64d\n",\r
+ ib_get_err_str( status ), cl_get_time_stamp()) );\r
+ return WSAEACCES;\r
+ }\r
\r
- *lpErrno = 0;\r
+ IBSP_EXIT( IBSP_DBG_CM );\r
return 0;\r
}\r
\r
{\r
ib_api_status_t status;\r
ib_cm_dreq_t cm_dreq;\r
- ib_qp_attr_t qp_attr;\r
+ ib_qp_mod_t qp_mod;\r
\r
- CL_ENTER( IBSP_DBG_CM, gdbg_lvl );\r
-\r
- socket_info->info.disconnect.event = CreateEvent( NULL, FALSE, FALSE, NULL );\r
+ IBSP_ENTER( IBSP_DBG_CM );\r
\r
memset( &cm_dreq, 0, sizeof(cm_dreq) );\r
\r
\r
status = ib_cm_dreq( &cm_dreq );\r
\r
- if( status != IB_SUCCESS )\r
- {\r
- CL_ERROR( IBSP_DBG_CM, gdbg_lvl, ("ib_cm_dreq failed (0x%d)\n", status) );\r
- goto done;\r
- }\r
-\r
- CL_TRACE( IBSP_DBG_CM, gdbg_lvl, ("wait for DREP event\n") );\r
-\r
- if( WaitForSingleObject( socket_info->info.disconnect.event, INFINITE ) != WAIT_OBJECT_0 )\r
+ /*\r
+ * If both sides initiate disconnection, we might get\r
+ * an invalid state or handle here.\r
+ */\r
+ if( status != IB_SUCCESS && status != IB_INVALID_STATE &&\r
+ status != IB_INVALID_HANDLE )\r
{\r
- CL_ERROR( IBSP_DBG_CM, gdbg_lvl, ("WaitForSingleObject failed\n") );\r
+ IBSP_ERROR( ("ib_cm_dreq returned %s\n", ib_get_err_str( status )) );\r
}\r
\r
- memset( &qp_attr, 0, sizeof(qp_attr) );\r
- status = ib_query_qp( socket_info->qp, &qp_attr );\r
+ /*\r
+ * Note that we don't care about getting the DREP - we move the QP to the\r
+ * error state now and flush all posted work requests. If the\r
+ * disconnection was graceful, we'll only have the pre-posted receives to\r
+ * flush. If the disconnection is ungraceful, we don't care if we\r
+ * interrupt transfers.\r
+ */\r
+\r
+ /* Force the QP to error state to flush posted receives. */\r
+ memset( &qp_mod, 0, sizeof(qp_mod) );\r
+ qp_mod.req_state = IB_QPS_ERROR;\r
+ status = ib_modify_qp( socket_info->qp, &qp_mod );\r
if( status != IB_SUCCESS )\r
{\r
- CL_ERROR( IBSP_DBG_EP, gdbg_lvl, ("ib_query_qp failed (%d)\n", status));\r
- goto done;\r
+ socket_info->send_cnt = 0;\r
+ socket_info->recv_cnt = 0;\r
}\r
-\r
- if( qp_attr.state != IB_QPS_ERROR )\r
- {\r
- ib_qp_mod_t qp_mod;\r
-\r
- fzprint(("%s():%d:0x%x:0x%x: socket=0x%p qp state=%d\n", __FUNCTION__,\r
- __LINE__, GetCurrentProcessId(),\r
- GetCurrentThreadId(), socket_info, qp_attr.state));\r
- memset( &qp_mod, 0, sizeof(qp_mod) );\r
- qp_mod.req_state = IB_QPS_ERROR;\r
- ib_modify_qp( socket_info->qp, &qp_mod );\r
- if( status != IB_SUCCESS )\r
- {\r
- CL_ERROR( IBSP_DBG_CM, gdbg_lvl,\r
- ("ib_mod_qp failed (0x%d)\n", status) );\r
- }\r
- Sleep( 100 );\r
- }\r
-\r
-done:\r
- CloseHandle( socket_info->info.disconnect.event );\r
-\r
- CL_EXIT( IBSP_DBG_CM, gdbg_lvl );\r
+ IBSP_EXIT( IBSP_DBG_CM );\r
}\r
/* Update the state of the socket context */\r
IBSP_CHANGE_SOCKET_STATE( new_socket_info, IBSP_ACCEPT );\r
\r
- ret = ib_accept( new_socket_info, &incoming->cm_req_received, lpErrno );\r
-\r
+ ret = ib_accept( new_socket_info, &incoming->cm_req_received );\r
if( ret )\r
{\r
IBSP_CHANGE_SOCKET_STATE( new_socket_info, IBSP_CREATE );\r
ib_net64_t dest_port_guid;\r
ib_path_rec_t path_rec;\r
\r
- CL_EXIT( IBSP_DBG_CONN, gdbg_lvl );\r
+ IBSP_ENTER( IBSP_DBG_CONN );\r
\r
UNUSED_PARAM( lpCalleeData );\r
UNUSED_PARAM( lpSQOS );\r
if( lpCallerData )\r
{\r
/* We don't support that. The current switch does not use it. */\r
- CL_ERROR( IBSP_DBG_CONN, gdbg_lvl, ("lpCallerData.len=%d\n", lpCallerData->len) );\r
+ IBSP_ERROR_EXIT( ("lpCallerData.len=%d\n", lpCallerData->len) );\r
*lpErrno = WSAEINVAL;\r
- goto error;\r
+ return SOCKET_ERROR;\r
}\r
\r
if( namelen < sizeof(struct sockaddr_in) )\r
{\r
- CL_ERROR( IBSP_DBG_CONN, gdbg_lvl,\r
+ IBSP_ERROR_EXIT(\r
("invalid remote address (%d)\n", socket_info->socket_state) );\r
*lpErrno = WSAEFAULT;\r
- goto error;\r
+ return SOCKET_ERROR;\r
}\r
\r
/* Check if the name (actually address) of peer entity is correct */\r
if( addr->sin_family != AF_INET ||\r
addr->sin_port == 0 || addr->sin_addr.s_addr == INADDR_ANY )\r
{\r
- CL_ERROR( IBSP_DBG_CONN, gdbg_lvl,\r
+ IBSP_ERROR_EXIT(\r
("peer entity address is invalid (%d, %d, %x)\n",\r
addr->sin_family, addr->sin_port, addr->sin_addr.s_addr) );\r
*lpErrno = WSAEADDRNOTAVAIL;\r
- goto error;\r
+ return SOCKET_ERROR;\r
}\r
\r
if( socket_info->local_addr.sin_addr.S_un.S_addr == addr->sin_addr.S_un.S_addr )\r
{\r
/* Loopback - let the regular stack take care of that. */\r
- CL_ERROR( IBSP_DBG_CONN, gdbg_lvl, ("Loopback!\n") );\r
+ IBSP_ERROR_EXIT( ("Loopback!\n") );\r
*lpErrno = WSAEADDRNOTAVAIL;\r
- goto error;\r
+ return SOCKET_ERROR;\r
}\r
\r
/* Get the GUID for that IP address. */\r
ret = query_guid_address( socket_info->port, addr->sin_addr.s_addr, &dest_port_guid );\r
if( ret )\r
{\r
- CL_ERROR( IBSP_DBG_CONN, gdbg_lvl,\r
+ IBSP_ERROR_EXIT(\r
("query_guid_address failed for IP %08x\n", addr->sin_addr.s_addr) );\r
*lpErrno = WSAEADDRNOTAVAIL;\r
- goto error;\r
+ return SOCKET_ERROR;\r
}\r
\r
CL_TRACE( IBSP_DBG_CONN, gdbg_lvl, ("got GUID %I64x for IP %s\n",\r
CL_NTOH64( dest_port_guid ), inet_ntoa( addr->sin_addr )) );\r
\r
+ if( dest_port_guid == socket_info->port->guid )\r
+ {\r
+ IBSP_ERROR_EXIT( ("Loopback!\n") );\r
+ *lpErrno = WSAEADDRNOTAVAIL;\r
+ return SOCKET_ERROR;\r
+ }\r
+\r
/* Get the path record */\r
ret = query_pr( socket_info->port, dest_port_guid, &path_rec );\r
if( ret )\r
{\r
- CL_ERROR( IBSP_DBG_CONN, gdbg_lvl,\r
+ IBSP_ERROR_EXIT(\r
("query_pr failed for IP %08x\n", addr->sin_addr.s_addr) );\r
*lpErrno = WSAEADDRNOTAVAIL;\r
- goto error;\r
+ return SOCKET_ERROR;\r
}\r
\r
cl_spinlock_acquire( &socket_info->mutex );\r
break;\r
\r
case IBSP_CONNECTED:\r
- cl_spinlock_release( &socket_info->mutex );\r
- CL_ERROR( IBSP_DBG_CONN, gdbg_lvl, ("Socket is already connected\n") );\r
+ IBSP_ERROR( ("Socket is already connected\n") );\r
*lpErrno = WSAEISCONN;\r
- goto error;\r
- break;\r
+ goto done;\r
\r
case IBSP_LISTEN:\r
- cl_spinlock_release( &socket_info->mutex );\r
- CL_ERROR( IBSP_DBG_CONN, gdbg_lvl, ("Socket is a listening socket\n") );\r
+ IBSP_ERROR( ("Socket is a listening socket\n") );\r
*lpErrno = WSAEINVAL;\r
- goto error;\r
+ goto done;\r
\r
default:\r
- cl_spinlock_release( &socket_info->mutex );\r
- CL_ERROR( IBSP_DBG_CONN, gdbg_lvl,\r
- ("Socket is not in the bound state (%s)\n",\r
+ IBSP_ERROR( ("Socket is not in the bound state (%s)\n",\r
IBSP_SOCKET_STATE_STR( socket_info->socket_state )) );\r
*lpErrno = WSAEINVAL;\r
- goto error;\r
- break;\r
+ goto done;\r
}\r
\r
/* Store the peer entity's address in socket context */\r
/* Update the socket state */\r
IBSP_CHANGE_SOCKET_STATE( socket_info, IBSP_CONNECT );\r
\r
- cl_spinlock_release( &socket_info->mutex );\r
-\r
/* Connect */\r
- ret = ib_connect( socket_info, &path_rec, lpErrno );\r
- if( ret )\r
+ *lpErrno = ib_connect( socket_info, &path_rec );\r
+ if( *lpErrno != WSAEWOULDBLOCK )\r
{\r
- cl_spinlock_acquire( &socket_info->mutex );\r
-\r
- if( socket_info->socket_state == IBSP_CONNECT )\r
- {\r
- /* We must be sure none destroyed our socket */\r
- IBSP_CHANGE_SOCKET_STATE( socket_info, IBSP_BIND );\r
- memset( &socket_info->peer_addr, 0, sizeof(struct sockaddr_in) );\r
- }\r
+ /* We must be sure none destroyed our socket */\r
+ IBSP_CHANGE_SOCKET_STATE( socket_info, IBSP_BIND );\r
+ memset( &socket_info->peer_addr, 0, sizeof(struct sockaddr_in) );\r
\r
- cl_spinlock_release( &socket_info->mutex );\r
-\r
- CL_ERROR( IBSP_DBG_CONN, gdbg_lvl, ("ib_connect failed (%d)\n", ret) );\r
-\r
- *lpErrno = WSAEHOSTUNREACH;\r
- goto error;\r
+ IBSP_ERROR( ("ib_connect failed (%d)\n", *lpErrno) );\r
}\r
\r
- /* Operation is pending */\r
- *lpErrno = WSAEWOULDBLOCK;\r
-\r
-error:\r
- CL_EXIT( IBSP_DBG_CONN, gdbg_lvl );\r
+done:\r
+ cl_spinlock_release( &socket_info->mutex );\r
+ IBSP_EXIT( IBSP_DBG_CONN );\r
return SOCKET_ERROR;\r
}\r
\r
*lpErrno = WSAENOTCONN;\r
return SOCKET_ERROR;\r
}\r
- cl_spinlock_release( &socket_info->mutex );\r
\r
ret = prepare_duplicate_socket( socket_info, dwProcessId );\r
+ cl_spinlock_release( &socket_info->mutex );\r
if( ret )\r
{\r
CL_TRACE_EXIT( IBSP_DBG_CONN, gdbg_lvl,\r
\r
case IBSP_LISTEN:\r
/* Change the backlog */\r
- socket_info->info.listen.backlog = backlog;\r
+ ib_listen_backlog( socket_info, backlog );\r
*lpErrno = 0;\r
break;\r
\r
default:\r
- CL_ERROR( IBSP_DBG_CONN, gdbg_lvl,\r
+ IBSP_ERROR(\r
("Invalid socket_state (%s)\n",\r
IBSP_SOCKET_STATE_STR( socket_info->socket_state )) );\r
*lpErrno = WSAEINVAL;\r