struct ibsp_socket_info *socket_info =\r
(struct ibsp_socket_info * __ptr64)p_cm_req_rec->context;\r
struct listen_incoming *incoming;\r
- ib_cm_mra_t mra;\r
\r
IBSP_ENTER( IBSP_DBG_CM );\r
\r
CL_ASSERT( socket_info );\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 )\r
- {\r
- /* Low on memory. */\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
- incoming->cm_req_received = *p_cm_req_rec;\r
- cl_memcpy( &incoming->params, p_cm_req_rec->p_req_pdata,\r
- sizeof(struct cm_req_params) );\r
- incoming->cm_req_received.p_req_pdata = (const uint8_t*)&incoming->params;\r
-\r
cl_spinlock_acquire( &socket_info->mutex );\r
\r
switch( socket_info->socket_state )\r
/* Already too many connection requests are queued */\r
IBSP_TRACE1( IBSP_DBG_CM,\r
("already too many incoming connections, rejecting\n") );\r
- HeapFree( g_ibsp.heap, 0, incoming );\r
ib_reject( p_cm_req_rec->h_cm_req, IB_REJ_USER_DEFINED );\r
break;\r
}\r
\r
+ incoming = HeapAlloc( g_ibsp.heap, 0, sizeof(struct listen_incoming) );\r
+ if( !incoming )\r
+ {\r
+ /* Low on memory. */\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
+ incoming->cm_req_received = *p_cm_req_rec;\r
+ cl_memcpy( &incoming->params, p_cm_req_rec->p_req_pdata,\r
+ sizeof(struct cm_req_params) );\r
+ incoming->cm_req_received.p_req_pdata = (const uint8_t*)&incoming->params;\r
+\r
/* Add to the waiting list */\r
cl_qlist_insert_tail( &socket_info->listen.list, &incoming->item );\r
\r
- /* Send MRA */\r
- mra.mra_length = 0;\r
- mra.p_mra_pdata = NULL;\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
break;\r
\r
{\r
int ret;\r
\r
- HeapFree( g_ibsp.heap, 0, incoming );\r
-\r
wait_cq_drain( socket_info );\r
\r
/* Non-blocking cancel since we're in CM callback context */\r
ib_cm_cancel( socket_info->listen.handle, NULL );\r
socket_info->listen.handle = NULL;\r
\r
-#if 0\r
- cl_spinlock_release( &socket_info->mutex );\r
- IBSP_ERROR_EXIT( ("rejecting\n") );\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
-\r
ret = ib_accept( socket_info, p_cm_req_rec );\r
if( ret )\r
{\r
\r
default:\r
IBSP_ERROR( ("socket is not listening anymore\n") );\r
- HeapFree( g_ibsp.heap, 0, incoming );\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
cl_spinlock_acquire( &socket_info->mutex );\r
\r
- if( socket_info->socket_state == IBSP_ACCEPT )\r
- {\r
- IBSP_CHANGE_SOCKET_STATE( socket_info, IBSP_CONNECTED );\r
- SetEvent( socket_info->h_event );\r
- }\r
- else if( socket_info->socket_state == IBSP_DUPLICATING_REMOTE )\r
+ if( socket_info->socket_state == IBSP_DUPLICATING_REMOTE )\r
{\r
struct _recv_wr *wr;\r
ib_api_status_t status;\r
socket_info->qp_error = 0;\r
IBSP_CHANGE_SOCKET_STATE( socket_info, IBSP_CONNECTED );\r
}\r
- else\r
+ else if( socket_info->socket_state != IBSP_CONNECTED )\r
{\r
/* The Socket might be closing */\r
IBSP_ERROR(\r
}\r
\r
\r
+/* Force the QP to error state to flush posted work requests. */\r
+static inline void\r
+__flush_qp(\r
+ IN struct ibsp_socket_info *p_socket )\r
+{\r
+ ib_qp_mod_t qp_mod;\r
+ ib_api_status_t status;\r
+\r
+ memset( &qp_mod, 0, sizeof(qp_mod) );\r
+ qp_mod.req_state = IB_QPS_ERROR;\r
+ status = ib_modify_qp( p_socket->qp, &qp_mod );\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ IBSP_ERROR( ("ib_modify_qp returned %s\n", ib_get_err_str( status )) );\r
+ p_socket->send_cnt = 0;\r
+ p_socket->recv_cnt = 0;\r
+ }\r
+}\r
+\r
+\r
/*\r
* A user-specified callback that is invoked after receiving a connection\r
* rejection message (REJ).\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
+ case IBSP_CONNECTED:\r
+ /*\r
+ * DISCONNECTED is a terminal state. We'll remove the connection\r
+ * when the socket gets destroyed.\r
+ */\r
+ IBSP_CHANGE_SOCKET_STATE( socket_info, IBSP_DISCONNECTED );\r
\r
- IBSP_CHANGE_SOCKET_STATE( socket_info, IBSP_CREATE );\r
- /* Fall through. */\r
+ socket_info->qp_error = WSAECONNABORTED;\r
+\r
+ __flush_qp( socket_info );\r
+ break;\r
\r
case IBSP_DUPLICATING_NEW:\r
/* Leave in that state. IBSPSocket will eventually return \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
+ /*\r
+ * DISCONNECTED is a terminal state. We'll remove the connection\r
+ * when the socket gets destroyed.\r
+ */\r
socket_info->qp_error = WSAECONNRESET;\r
}\r
\r
{\r
ib_api_status_t status;\r
ib_cm_dreq_t cm_dreq;\r
- ib_qp_mod_t qp_mod;\r
\r
IBSP_ENTER( IBSP_DBG_CM );\r
\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
- IBSP_ERROR( ("ib_modify_qp returned %s\n", ib_get_err_str( status )) );\r
- socket_info->send_cnt = 0;\r
- socket_info->recv_cnt = 0;\r
- }\r
+ /* Move the QP to error to flush any work requests. */\r
+ __flush_qp( socket_info );\r
\r
IBSP_EXIT( IBSP_DBG_CM );\r
}\r
}\r
\r
\r
+static SOCKET\r
+accept_socket(\r
+ IN struct ibsp_socket_info *p_socket,\r
+ IN struct listen_incoming *p_incoming,\r
+ IN struct ibsp_port *p_port,\r
+ OUT LPINT lpErrno )\r
+{\r
+ struct ibsp_socket_info *new_socket_info;\r
+ int ret;\r
+\r
+ IBSP_ENTER( IBSP_DBG_CONN );\r
+\r
+ /* Create a new socket here */\r
+ new_socket_info = create_socket_info( lpErrno );\r
+ if( !new_socket_info )\r
+ {\r
+ ib_reject(\r
+ p_incoming->cm_req_received.h_cm_req, IB_REJ_INSUF_RESOURCES );\r
+\r
+ IBSP_ERROR_EXIT( ("create_socket_info failed (%d)\n", *lpErrno) );\r
+ return INVALID_SOCKET;\r
+ }\r
+\r
+ /* Time to allocate our IB QP */\r
+ new_socket_info->port = p_port;\r
+ *lpErrno = ib_create_socket( new_socket_info );\r
+ if( *lpErrno )\r
+ {\r
+ deref_socket_info( new_socket_info );\r
+\r
+ ib_reject(\r
+ p_incoming->cm_req_received.h_cm_req, IB_REJ_INSUF_QP );\r
+\r
+ IBSP_ERROR_EXIT( ("ib_create_socket failed (%d)\n", *lpErrno) );\r
+ return INVALID_SOCKET;\r
+ }\r
+\r
+ /* Store the IP address and port number in the socket context */\r
+ new_socket_info->local_addr = p_incoming->params.dest;\r
+\r
+ /* Copy the socket context info from parent socket context */\r
+ new_socket_info->socket_options = p_socket->socket_options;\r
+\r
+ IBSP_TRACE( IBSP_DBG_CONN,\r
+ ("The socket address of connecting entity is\n") );\r
+ DebugPrintSockAddr( IBSP_DBG_CONN, gdbg_lvl, &p_incoming->params.source );\r
+\r
+ new_socket_info->peer_addr = p_incoming->params.source;\r
+\r
+ cl_spinlock_acquire( &new_socket_info->mutex );\r
+ /* Update the state of the socket context */\r
+ IBSP_CHANGE_SOCKET_STATE( new_socket_info, IBSP_CONNECTED );\r
+\r
+ *lpErrno = ib_accept( new_socket_info, &p_incoming->cm_req_received );\r
+ if( *lpErrno )\r
+ {\r
+ IBSP_CHANGE_SOCKET_STATE( new_socket_info, IBSP_CREATE );\r
+ cl_spinlock_release( &new_socket_info->mutex );\r
+\r
+ if( *lpErrno == WSAEADDRINUSE )\r
+ {\r
+ /* Be nice and reject that connection. */\r
+ ib_reject( p_incoming->cm_req_received.h_cm_req, IB_REJ_INSUF_QP );\r
+ }\r
+\r
+ g_ibsp.up_call_table.lpWPUCloseSocketHandle(\r
+ new_socket_info->switch_socket, &ret );\r
+ new_socket_info->switch_socket = INVALID_SOCKET;\r
+ STAT_DEC( wpusocket_num );\r
+\r
+ ib_destroy_socket( new_socket_info );\r
+ deref_socket_info( new_socket_info );\r
+ return INVALID_SOCKET;\r
+ }\r
+\r
+ cl_spinlock_acquire( &g_ibsp.socket_info_mutex );\r
+ cl_qlist_insert_tail(\r
+ &g_ibsp.socket_info_list, &new_socket_info->item );\r
+ cl_spinlock_release( &g_ibsp.socket_info_mutex );\r
+\r
+ cl_spinlock_release( &new_socket_info->mutex );\r
+\r
+ IBSP_TRACE_EXIT( IBSP_DBG_CONN,\r
+ ("returns new socket (0x%p)\n", new_socket_info) );\r
+ return (SOCKET)new_socket_info;\r
+}\r
+\r
+\r
/* Function: IBSPAccept\r
*\r
* Description:\r
OUT LPINT lpErrno )\r
{\r
struct ibsp_socket_info *socket_info = (struct ibsp_socket_info *)s;\r
- struct ibsp_socket_info *new_socket_info;\r
- int ret;\r
WSABUF caller_id;\r
WSABUF callee_id;\r
struct listen_incoming *incoming;\r
struct ibsp_port *port;\r
+ ib_cm_mra_t mra;\r
\r
IBSP_ENTER( IBSP_DBG_CONN );\r
\r
IBSP_TRACE( IBSP_DBG_CONN,\r
("IBSPAccept: Found pending connection on this socket\n") );\r
\r
- incoming = PARENT_STRUCT(cl_qlist_head( &socket_info->listen.list ),\r
+ incoming = PARENT_STRUCT(cl_qlist_remove_head( &socket_info->listen.list ),\r
struct listen_incoming, item);\r
+\r
+ /* Signal the event again if there are more connection requests. */\r
+ if( cl_qlist_count( &socket_info->listen.list ) )\r
+ ibsp_post_select_event( socket_info, FD_ACCEPT, 0 );\r
+ cl_spinlock_release( &socket_info->mutex );\r
+\r
port = socket_info->port;\r
\r
/* Find the destination IP address */\r
- if( port == NULL )\r
+ if( !port )\r
{\r
/* The socket was bound to INADDR_ANY. We must find the correct port\r
* for the new socket. */\r
port = get_port_from_ip_address( incoming->params.dest.sin_addr );\r
- if( port == NULL )\r
+ if( !port )\r
{\r
IBSP_ERROR(\r
("incoming destination IP address not local (%s)\n",\r
ib_gid_get_guid( &incoming->cm_req_received.primary_path.sgid )) );\r
\r
reject:\r
- /* The request is invalid. Remove it from the list and reject it. */\r
- cl_qlist_remove_item( &socket_info->listen.list, &incoming->item );\r
- cl_spinlock_release( &socket_info->mutex );\r
-\r
ib_reject( incoming->cm_req_received.h_cm_req, IB_REJ_INSUF_QP );\r
\r
HeapFree( g_ibsp.heap, 0, incoming );\r
incoming->params.dest.sin_family) );\r
\r
/* Call the conditional function */\r
- ret = lpfnCondition( &caller_id, NULL, NULL, NULL,\r
- &callee_id, NULL, NULL, dwCallbackData );\r
-\r
- switch( ret )\r
+ switch( lpfnCondition( &caller_id, NULL, NULL, NULL,\r
+ &callee_id, NULL, NULL, dwCallbackData ) )\r
{\r
- case CF_REJECT:\r
- cl_qlist_remove_item( &socket_info->listen.list, &incoming->item );\r
- cl_spinlock_release( &socket_info->mutex );\r
+ default:\r
+ /* Should never happen */\r
+ IBSP_ERROR(\r
+ ("Conditional routine returned undocumented code\n") );\r
+ /* Fall through. */\r
\r
+ case CF_REJECT:\r
IBSP_TRACE1( IBSP_DBG_CONN,\r
("Conditional routine returned CF_REJECT\n") );\r
\r
return INVALID_SOCKET;\r
\r
case CF_DEFER:\r
+ /* Send MRA */\r
+ mra.mra_length = 0;\r
+ mra.p_mra_pdata = NULL;\r
+ mra.svc_timeout = 0x15;\r
+ ib_cm_mra( incoming->cm_req_received.h_cm_req, &mra );\r
+\r
+ /* Put the item back at the head of the list. */\r
+ cl_spinlock_acquire( &socket_info->mutex );\r
+ cl_qlist_insert_head( &socket_info->listen.list, &incoming->item );\r
cl_spinlock_release( &socket_info->mutex );\r
\r
IBSP_TRACE1( IBSP_DBG_CONN,\r
("Conditional routine returned CF_DEFER\n") );\r
- /* TODO: Send MRA */\r
+\r
*lpErrno = WSATRY_AGAIN;\r
IBSP_EXIT( IBSP_DBG_CONN );\r
return INVALID_SOCKET;\r
\r
case CF_ACCEPT:\r
break;\r
-\r
- default:\r
- /* Should never happen */\r
- cl_spinlock_release( &socket_info->mutex );\r
- IBSP_ERROR(\r
- ("Conditional routine returned undocumented code (%d)\n", ret) );\r
- CL_ASSERT( 0 );\r
- *lpErrno = WSAECONNREFUSED;\r
- IBSP_EXIT( IBSP_DBG_CONN );\r
- return INVALID_SOCKET;\r
}\r
\r
- /* Create a new socket here */\r
- new_socket_info = create_socket_info( lpErrno );\r
- if( !new_socket_info )\r
+ s = accept_socket( socket_info, incoming, port, lpErrno );\r
+ if( s != INVALID_SOCKET )\r
{\r
- cl_spinlock_release( &socket_info->mutex );\r
-\r
- IBSP_ERROR_EXIT( ("create_socket_info failed (%d)\n", *lpErrno) );\r
- return INVALID_SOCKET;\r
+ /* Store the client socket address information */\r
+ memcpy( addr, &incoming->params.source, sizeof(struct sockaddr_in) );\r
+ *addrlen = sizeof(struct sockaddr_in);\r
}\r
\r
- /* Time to allocate our IB QP */\r
- new_socket_info->port = port;\r
- *lpErrno = ib_create_socket( new_socket_info );\r
- if( *lpErrno )\r
- {\r
- cl_spinlock_release( &socket_info->mutex );\r
- deref_socket_info( new_socket_info );\r
-\r
- IBSP_ERROR_EXIT( ("ib_create socket failed with %d\n", *lpErrno) );\r
- return INVALID_SOCKET;\r
- }\r
-\r
- /* Store the IP address and port number in the socket context */\r
- new_socket_info->local_addr = incoming->params.dest;\r
-\r
- cl_qlist_remove_item( &socket_info->listen.list, &incoming->item );\r
- /* Signal the event again if there are more connection requests. */\r
- if( cl_qlist_count( &socket_info->listen.list ) )\r
- ibsp_post_select_event( socket_info, FD_ACCEPT, 0 );\r
-\r
- cl_spinlock_release( &socket_info->mutex );\r
-\r
- /* Copy the socket context info from parent socket context */\r
- new_socket_info->socket_options = socket_info->socket_options;\r
-\r
- /* Store the client socket address information */\r
- memcpy( addr, &incoming->params.source, sizeof(struct sockaddr_in) );\r
- *addrlen = sizeof(struct sockaddr_in);\r
-\r
- IBSP_TRACE( IBSP_DBG_CONN,\r
- ("The socket address of connecting entity is\n") );\r
- DebugPrintSockAddr( IBSP_DBG_CONN, gdbg_lvl, &incoming->params.source );\r
-\r
- new_socket_info->peer_addr = incoming->params.source;\r
-\r
- new_socket_info->h_event = CreateEvent( NULL, FALSE, FALSE, NULL );\r
-\r
- cl_spinlock_acquire( &new_socket_info->mutex );\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 );\r
- if( ret )\r
- {\r
- IBSP_CHANGE_SOCKET_STATE( new_socket_info, IBSP_CREATE );\r
- cl_spinlock_release( &new_socket_info->mutex );\r
-\r
- if( g_ibsp.up_call_table.lpWPUCloseSocketHandle(\r
- new_socket_info->switch_socket, &ret ) == SOCKET_ERROR )\r
- {\r
- IBSP_ERROR( ("WPUCloseSocketHandle failed: %d\n", ret) );\r
- }\r
- else\r
- {\r
- STAT_DEC( wpusocket_num );\r
- }\r
- new_socket_info->switch_socket = INVALID_SOCKET;\r
-\r
- CloseHandle( new_socket_info->h_event );\r
-\r
- ib_destroy_socket( new_socket_info );\r
-\r
- deref_socket_info( new_socket_info );\r
-\r
- /* Be nice and reject that connection. */\r
- ib_reject( incoming->cm_req_received.h_cm_req, IB_REJ_INSUF_QP );\r
-\r
- HeapFree( g_ibsp.heap, 0, incoming );\r
- *lpErrno = ret;\r
-\r
- IBSP_ERROR_EXIT( ("ib_accept failed (%d)\n", ret) );\r
-\r
- return INVALID_SOCKET;\r
- }\r
- else\r
- {\r
- cl_spinlock_release( &new_socket_info->mutex );\r
- HeapFree( g_ibsp.heap, 0, incoming );\r
-\r
- if( WaitForSingleObject( new_socket_info->h_event, INFINITE ) == WAIT_OBJECT_0 )\r
- {\r
- CloseHandle( new_socket_info->h_event );\r
- new_socket_info->h_event = NULL;\r
-\r
- cl_spinlock_acquire( &new_socket_info->mutex );\r
+ HeapFree( g_ibsp.heap, 0, incoming );\r
\r
- if( new_socket_info->socket_state == IBSP_CONNECTED )\r
- {\r
- cl_spinlock_acquire( &g_ibsp.socket_info_mutex );\r
- cl_qlist_insert_tail( &g_ibsp.socket_info_list, &new_socket_info->item );\r
- cl_spinlock_release( &g_ibsp.socket_info_mutex );\r
-\r
- cl_spinlock_release( &new_socket_info->mutex );\r
- }\r
- else\r
- {\r
- IBSP_ERROR(\r
- ("ib_accept failed - socket state is %s\n",\r
- IBSP_SOCKET_STATE_STR( new_socket_info->socket_state )) );\r
-\r
- cl_spinlock_release( &new_socket_info->mutex );\r
-\r
- /* The accept failed (by a REJ for instance). */\r
-\r
- /* Free the socket descriptor */\r
- if( g_ibsp.up_call_table.lpWPUCloseSocketHandle(\r
- new_socket_info->switch_socket, lpErrno ) == SOCKET_ERROR )\r
- {\r
- IBSP_ERROR(\r
- ("WPUCloseSocketHandle failed: %d\n", *lpErrno) );\r
- }\r
- else\r
- {\r
- STAT_DEC( wpusocket_num );\r
- }\r
- new_socket_info->switch_socket = INVALID_SOCKET;\r
-\r
- ib_destroy_socket( new_socket_info );\r
- deref_socket_info( new_socket_info );\r
-\r
- *lpErrno = WSAEACCES;\r
-\r
- new_socket_info = (struct ibsp_socket_info *)INVALID_SOCKET;\r
- }\r
-\r
- IBSP_TRACE_EXIT( IBSP_DBG_CONN,\r
- ("returns new SocketID (0x%x)\n", new_socket_info) );\r
-\r
- return (SOCKET) new_socket_info;\r
- }\r
- else\r
- {\r
- CloseHandle( new_socket_info->h_event );\r
- new_socket_info->h_event = NULL;\r
-\r
- IBSP_ERROR_EXIT( ("wait for ib_accept failed\n") );\r
-\r
- *lpErrno = WSAEACCES;\r
- return INVALID_SOCKET;\r
- }\r
- }\r
-\r
- /* Unreachable */\r
+ IBSP_EXIT( IBSP_DBG_CONN );\r
+ return s;\r
}\r
\r
\r
cl_atomic_inc( &g_ibsp.CloseSocket_count );\r
#endif\r
\r
- cl_spinlock_acquire( &g_ibsp.socket_info_mutex );\r
- cl_qlist_remove_item( &g_ibsp.socket_info_list, &socket_info->item );\r
- cl_spinlock_release( &g_ibsp.socket_info_mutex );\r
-\r
shutdown_and_destroy_socket_info( socket_info );\r
\r
IBSP_EXIT( IBSP_DBG_CONN );\r
socket_info, lpProtocolInfo->dwProviderReserved );\r
if( *lpErrno )\r
{\r
- int error;\r
-\r
- if( g_ibsp.up_call_table.lpWPUCloseSocketHandle(\r
- socket_info->switch_socket, &error ) == SOCKET_ERROR )\r
- {\r
- IBSP_ERROR( ("WPUCloseSocketHandle failed: %d\n", error) );\r
- }\r
- else\r
- {\r
- STAT_DEC( wpusocket_num );\r
- }\r
-\r
- socket_info->switch_socket = INVALID_SOCKET;\r
-\r
deref_socket_info( socket_info );\r
IBSP_ERROR(\r
("setup_duplicate_socket failed with %d\n", *lpErrno) );\r