|
version 1.3, 2005/03/16 14:11:26
|
version 1.5, 2005/03/16 15:12:06
|
|
|
|
| { | { |
| int i; | int i; |
| server_memory *mem = TlsGetValue ( tls ); | server_memory *mem = TlsGetValue ( tls ); |
| |
|
| for (i = 0; i < MAX_CLIENTS; i++ ) | for (i = 0; i < MAX_CLIENTS; i++ ) |
| { | { |
| LocalFree ( (HANDLE) mem->sock[i].buf ); | LocalFree ( (HANDLE) mem->sock[i].buf ); |
|
|
|
| static sock_info* GetClientSockInfo( server_memory* servMem, SOCKET sockToFind ) | static sock_info* GetClientSockInfo( server_memory* servMem, SOCKET sockToFind ) |
| { | { |
| | |
| // Looping through all the possible clients |
/* Looping through all the possible clients */ |
| int clientNum; | int clientNum; |
| for( clientNum = 0; clientNum < MAX_CLIENTS; clientNum++ ){ | for( clientNum = 0; clientNum < MAX_CLIENTS; clientNum++ ){ |
| | |
| // When the match is found, return the pointer to that sock_info struct |
/* When the match is found, return the pointer to that sock_info struct */ |
| if( servMem->sock[clientNum].s == sockToFind ){ | if( servMem->sock[clientNum].s == sockToFind ){ |
| | |
| return &(servMem->sock[clientNum]); | return &(servMem->sock[clientNum]); |
|
|
|
| | |
| } | } |
| | |
| // Did not find a match. |
/* Did not find a match. */ |
| return NULL; | return NULL; |
| | |
| } | } |
|
|
|
| static sock_info* GetNextOpenSock( server_memory* servMem ) | static sock_info* GetNextOpenSock( server_memory* servMem ) |
| { | { |
| | |
| // Loop through sock array of servMem |
/* Loop through sock array of servMem */ |
| int clientNum; | int clientNum; |
| for( clientNum = 0; clientNum < MAX_CLIENTS; clientNum++ ){ | for( clientNum = 0; clientNum < MAX_CLIENTS; clientNum++ ){ |
| | |
| // when an open slot is found, return |
/* when an open slot is found, return */ |
| if( servMem->sock[clientNum].s == INVALID_SOCKET ) | if( servMem->sock[clientNum].s == INVALID_SOCKET ) |
| return &(servMem->sock[clientNum]); | return &(servMem->sock[clientNum]); |
| | |
| } | } |
| | |
| // When there is no more open socket, return NULL |
/* When there is no more open socket, return NULL */ |
| return NULL; | return NULL; |
| | |
| } | } |
|
|
|
| static BOOL noOpenSock( server_memory* servMem ) | static BOOL noOpenSock( server_memory* servMem ) |
| { | { |
| | |
| // Loop through sock array of servMem |
/* Loop through sock array of servMem */ |
| int clientNum; | int clientNum; |
| for( clientNum = 0; clientNum < MAX_CLIENTS; clientNum++ ){ | for( clientNum = 0; clientNum < MAX_CLIENTS; clientNum++ ){ |
| | |
| // if any socket != INVALID_SOCKET, there is an open socket |
/* if any socket != INVALID_SOCKET, there is an open socket */ |
| if( servMem->sock[clientNum].s != INVALID_SOCKET ) | if( servMem->sock[clientNum].s != INVALID_SOCKET ) |
| return FALSE; | return FALSE; |
| | |
| } | } |
| | |
| // no open sockets |
/* no open sockets */ |
| return TRUE; | return TRUE; |
| | |
| } | } |
|
|
|
| int n_sent = 0, sendLen, err; | int n_sent = 0, sendLen, err; |
| int id = GetCurrentThreadId(); | int id = GetCurrentThreadId(); |
| | |
| // send any data that hasn't been sent yet |
/* send any data that hasn't been sent yet */ |
| while( sockInfo->nsent < sockInfo->nread ){ | while( sockInfo->nsent < sockInfo->nread ){ |
| | |
| // find out the buffer length to send |
/* find out the buffer length to send */ |
| sendLen = min( sockInfo->nread - sockInfo->nsent, servBufLen ); | sendLen = min( sockInfo->nread - sockInfo->nsent, servBufLen ); |
| | |
| // send the data |
/* send the data */ |
| n_sent = send( sockInfo->s, sockInfo->buf + sockInfo->nsent, sendLen, 0 ); | n_sent = send( sockInfo->s, sockInfo->buf + sockInfo->nsent, sendLen, 0 ); |
| | |
| // If there was an error, break |
/* If there was an error, break */ |
| if( n_sent == SOCKET_ERROR ) | if( n_sent == SOCKET_ERROR ) |
| break; | break; |
| | |
| // update the number bytes sent |
/* update the number bytes sent */ |
| sockInfo->nsent += n_sent; | sockInfo->nsent += n_sent; |
| | |
| } | } |
| | |
| // check the error |
/* check the error */ |
| if( n_sent == SOCKET_ERROR && ( err = WSAGetLastError () ) != WSAEWOULDBLOCK ) | if( n_sent == SOCKET_ERROR && ( err = WSAGetLastError () ) != WSAEWOULDBLOCK ) |
| ok( 0, "async_server (%x): send error: %d\n", id, err ); | ok( 0, "async_server (%x): send error: %d\n", id, err ); |
| | |
|
|
|
| | |
| trace( "async_server (%x): accept event\n", id ); | trace( "async_server (%x): accept event\n", id ); |
| | |
| // Find the next available socket |
/* Find the next available socket */ |
| sockInfo = GetNextOpenSock( mem ); | sockInfo = GetNextOpenSock( mem ); |
| ok( sockInfo != NULL, "async_server (%x): no more open socket\n", id ); | ok( sockInfo != NULL, "async_server (%x): no more open socket\n", id ); |
| | |
| // accept connection |
/* accept connection */ |
| sockInfo->s = accept( mem->s, (struct sockaddr*) &peer, &addrLen ); | sockInfo->s = accept( mem->s, (struct sockaddr*) &peer, &addrLen ); |
| wsa_ok( sockInfo->s, INVALID_SOCKET !=, "async_server (%lx): accept failed: %d\n" ); | wsa_ok( sockInfo->s, INVALID_SOCKET !=, "async_server (%lx): accept failed: %d\n" ); |
| | |
| // check the address retrieved from accept() is valid |
/* check the address retrieved from accept() is valid */ |
| ok( peer.sin_addr.s_addr == inet_addr( inetAddr ), "async_server (%x): strange peer address\n", id ); | ok( peer.sin_addr.s_addr == inet_addr( inetAddr ), "async_server (%x): strange peer address\n", id ); |
| | |
| // make this newly accepted socket asynchronous |
/* make this newly accepted socket asynchronous */ |
| err = WSAAsyncSelect( sockInfo->s, async_params.hwnd, ASYNC_EVENT, FD_ACCEPT | FD_READ | FD_WRITE | FD_CLOSE ); | err = WSAAsyncSelect( sockInfo->s, async_params.hwnd, ASYNC_EVENT, FD_ACCEPT | FD_READ | FD_WRITE | FD_CLOSE ); |
| wsa_ok( err, SOCKET_ERROR !=, "async_server (%lx): WSAAsyncSelect failed: %d\n" ); | wsa_ok( err, SOCKET_ERROR !=, "async_server (%lx): WSAAsyncSelect failed: %d\n" ); |
| | |
|
|
|
| | |
| case FD_WRITE: | case FD_WRITE: |
| | |
| // get the sock_info* of this client socket |
/* get the sock_info* of this client socket */ |
| sockInfo = GetClientSockInfo( mem, clientSock ); | sockInfo = GetClientSockInfo( mem, clientSock ); |
| ok( sockInfo != NULL, "async_server (%x): socket to write to is not open\n", id ); | ok( sockInfo != NULL, "async_server (%x): socket to write to is not open\n", id ); |
| | |
| // try sending any remaining data |
/* try sending any remaining data */ |
| try_send_all_buf( sockInfo, servBufLen ); | try_send_all_buf( sockInfo, servBufLen ); |
| break; | break; |
| | |
| case FD_READ: | case FD_READ: |
| | |
| // get the sock_info* of this client socket |
/* get the sock_info* of this client socket */ |
| sockInfo = GetClientSockInfo( mem, clientSock ); | sockInfo = GetClientSockInfo( mem, clientSock ); |
| ok( sockInfo != NULL, "async_server (%x): socket to read from is not open\n", id ); | ok( sockInfo != NULL, "async_server (%x): socket to read from is not open\n", id ); |
| | |
| // retrieve the data |
/* retrieve the data */ |
| n_recvd = recv( sockInfo->s, sockInfo->buf + sockInfo->nread, servBufLen, 0 ); | n_recvd = recv( sockInfo->s, sockInfo->buf + sockInfo->nread, servBufLen, 0 ); |
| if( n_recvd == SOCKET_ERROR && ( err = WSAGetLastError () ) != WSAEWOULDBLOCK ) | if( n_recvd == SOCKET_ERROR && ( err = WSAGetLastError () ) != WSAEWOULDBLOCK ) |
| ok( 0, "async_server (%x): recv error: %d\n", id, err ); | ok( 0, "async_server (%x): recv error: %d\n", id, err ); |
| | |
| // record number of bytes read so far |
/* record number of bytes read so far */ |
| if( n_recvd != SOCKET_ERROR ) | if( n_recvd != SOCKET_ERROR ) |
| sockInfo->nread += n_recvd; | sockInfo->nread += n_recvd; |
| | |
| // send the remaining data |
/* send the remaining data */ |
| try_send_all_buf( sockInfo, servBufLen ); | try_send_all_buf( sockInfo, servBufLen ); |
| break; | break; |
| | |
| case FD_CLOSE: | case FD_CLOSE: |
| | |
| // Client closed connection - close the connection with this server. |
/* Client closed connection - close the connection with this server. */ |
| trace( "async_server (%x): close event\n", id ); | trace( "async_server (%x): close event\n", id ); |
| sockInfo = GetClientSockInfo( mem, clientSock ); | sockInfo = GetClientSockInfo( mem, clientSock ); |
| ok( sockInfo != NULL, "async_server (%x): socket to close is not open\n", id ); | ok( sockInfo != NULL, "async_server (%x): socket to close is not open\n", id ); |
| | |
| // Check the data it received |
/* Check the data it received */ |
| n_expected = gen->n_chunks * gen->chunk_size; | n_expected = gen->n_chunks * gen->chunk_size; |
| ok( sockInfo->nread == n_expected, | ok( sockInfo->nread == n_expected, |
| "async_server (%x): received less data than expected: %d of %d\n", id, sockInfo->nread, n_expected ); | "async_server (%x): received less data than expected: %d of %d\n", id, sockInfo->nread, n_expected ); |
|
|
|
| p = test_buffer( sockInfo->buf, gen->chunk_size, gen->n_chunks ); | p = test_buffer( sockInfo->buf, gen->chunk_size, gen->n_chunks ); |
| ok( p == NULL, "async_server (%x): test pattern error: %d\n", id, p - sockInfo->buf); | ok( p == NULL, "async_server (%x): test pattern error: %d\n", id, p - sockInfo->buf); |
| | |
| // clean up |
/* clean up */ |
| wsa_ok( closesocket( sockInfo->s ), 0 ==, "async_server (%lx): closesocket error: %d\n" ); | wsa_ok( closesocket( sockInfo->s ), 0 ==, "async_server (%lx): closesocket error: %d\n" ); |
| sockInfo->s = INVALID_SOCKET; | sockInfo->s = INVALID_SOCKET; |
| | |
| // If all sockets are closed, kill the server |
/* If all sockets are closed, kill the server */ |
| if( noOpenSock( mem ) ){ | if( noOpenSock( mem ) ){ |
| | |
| trace( "async_server (%x) exiting\n", id ); | trace( "async_server (%x) exiting\n", id ); |
|
|
|
| set_so_opentype( FALSE ); /* non-overlapped */ | set_so_opentype( FALSE ); /* non-overlapped */ |
| server_start( par ); | server_start( par ); |
| | |
| // set up async_params structure |
/* set up async_params structure */ |
| memset( &async_params, 0, sizeof( async_params ) ); | memset( &async_params, 0, sizeof( async_params ) ); |
| async_params.svc_params = par; | async_params.svc_params = par; |
| async_params.mem = TlsGetValue( tls ); | async_params.mem = TlsGetValue( tls ); |
| | |
| // Listen to socket |
|
| wsa_ok( listen ( (async_params.mem)->s, SOMAXCONN ), 0 ==, "async_server (%lx): listen failed: %d\n"); | wsa_ok( listen ( (async_params.mem)->s, SOMAXCONN ), 0 ==, "async_server (%lx): listen failed: %d\n"); |
| | |
| // Get the current instance |
/* Get the current instance */ |
| HINSTANCE instance = GetModuleHandle( NULL ); | HINSTANCE instance = GetModuleHandle( NULL ); |
| ok( instance != NULL, "async_server (%x):GetModuleHandle error %ld\n", id, GetLastError() ); | ok( instance != NULL, "async_server (%x):GetModuleHandle error %ld\n", id, GetLastError() ); |
| | |
| // Create a hiddent window to handle async events |
/* Create a hiddent window to handle async events */ |
| WNDCLASS windowClass; | WNDCLASS windowClass; |
| windowClass.lpszClassName = "Hidden_Winsock_Window"; | windowClass.lpszClassName = "Hidden_Winsock_Window"; |
| windowClass.style = CS_HREDRAW | CS_VREDRAW; | windowClass.style = CS_HREDRAW | CS_VREDRAW; |
|
|
|
| ok( retVal != -1, "async_server (%x): GetMessage error %ld\n", id, GetLastError() ); | ok( retVal != -1, "async_server (%x): GetMessage error %ld\n", id, GetLastError() ); |
| if( retVal == -1 ){ | if( retVal == -1 ){ |
| | |
| // exit so that the server won't block |
/* exit so that the server won't block */ |
| trace( "async_server (%x): exiting\n", id ); | trace( "async_server (%x): exiting\n", id ); |
| server_stop(); | server_stop(); |
| | |
| } | } |
| | |
| // Translate and dispatch the message |
/* Translate and dispatch the message */ |
| TranslateMessage( &msg ); | TranslateMessage( &msg ); |
| DispatchMessage( &msg ); | DispatchMessage( &msg ); |
| | |