Author: zhu
Date: Wed Jul 13 21:01:53 2016
New Revision: 71935
URL:
http://svn.reactos.org/svn/reactos?rev=71935&view=rev
Log:
Changed test programs. Server now echoes messages sent by client, and client is now
multi-threaded.
Modified spinlocks to serialize access to metadata as well as linked lists. Very
inefficient, and does not pass my own test bench right now.
Defined and wrote initialization code for global variables intended solely as debugging
aids.
Modified:
branches/GSoC_2016/lwIP-tcpip/base/applications/network/tcpclient/main.c
branches/GSoC_2016/lwIP-tcpip/base/applications/network/tcpserver/main.c
branches/GSoC_2016/lwIP-tcpip/drivers/network/tcpip/address.c
Modified: branches/GSoC_2016/lwIP-tcpip/base/applications/network/tcpclient/main.c
URL:
http://svn.reactos.org/svn/reactos/branches/GSoC_2016/lwIP-tcpip/base/appli…
==============================================================================
--- branches/GSoC_2016/lwIP-tcpip/base/applications/network/tcpclient/main.c [iso-8859-1]
(original)
+++ branches/GSoC_2016/lwIP-tcpip/base/applications/network/tcpclient/main.c [iso-8859-1]
Wed Jul 13 21:01:53 2016
@@ -2,48 +2,106 @@
#include <stdio.h>
#include <winsock2.h>
+#define LENGTH 255
+#define NUM_CLIENTS 4
+
+DWORD WINAPI ClientThreadMain(LPVOID lpParam) {
+ SOCKET Sock;
+
+ struct sockaddr_in ServerAddr;
+
+ char buff[LENGTH];
+
+ int self;
+ int ret;
+ int len;
+
+ self = (int)lpParam;
+
+ printf("Client %d startup\n", self);
+
+ Sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+ if (Sock == INVALID_SOCKET) {
+ printf("Client %d failed to create socket: %d\n", self,
WSAGetLastError());
+ return 1;
+ }
+
+ ServerAddr.sin_family = AF_INET;
+ ServerAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
+ ServerAddr.sin_port = htons(10000);
+
+ ret = connect(Sock, (struct sockaddr *)&ServerAddr, sizeof(struct sockaddr_in));
+ if (ret == SOCKET_ERROR) {
+ printf("Client %d failed to connect: %d\n", self, WSAGetLastError());
+ closesocket(Sock);
+ return 1;
+ }
+
+ sprintf(buff, "Client %d pinging server", self);
+ len = strlen(buff);
+ ret = send(Sock, buff, len, 0);
+ if (ret != len) {
+ printf("Client %d failed to send properly. Should send %d bytes, send()
returned %d\n WSA Error: %d\n",
+ self, len, ret, WSAGetLastError());
+ closesocket(Sock);
+ return 1;
+ }
+
+ ret = recv(Sock, buff, LENGTH, 0);
+ buff[LENGTH - 1] = '\0';
+ if (ret <= 0) {
+ printf("Client %d received no response from server: %d\n", self,
WSAGetLastError());
+ }
+ else {
+ printf("Client %d received %d-byte response from server:\n %s\n",
+ self, ret, buff);
+ }
+
+ closesocket(Sock);
+
+ printf("Client %d exit\n", self);
+
+ return 0;
+}
+
int wmain(int argc, LPWSTR argv[]) {
- WSADATA wsa;
- SOCKET sock;
- struct sockaddr_in server;
+ WSADATA wsa;
+ HANDLE ClientThreadHandles[NUM_CLIENTS];
+ DWORD ClientThreadIDs[NUM_CLIENTS];
- int ret;
-
- char buff[256];
+ char buff[LENGTH];
- ret = WSAStartup(MAKEWORD(2, 2), &wsa);
- if (ret != 0) {
- printf("Windows Socket API Startup Failed: %d", WSAGetLastError());
- return 1;
- }
+ int ret;
+ int i;
- printf("Attempt socket creation\n");
- fgets(&buff[0], 255, stdin);
- sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
- if (sock == INVALID_SOCKET) {
- printf("Socket Creation Failed: %d", WSAGetLastError());
- return 1;
- }
-
- server.sin_addr.s_addr = inet_addr("127.0.0.1");
- server.sin_family = AF_INET;
- server.sin_port = htons(10000);
+ ret = WSAStartup(MAKEWORD(2, 2), &wsa);
+ if (ret != 0) {
+ printf("Windows Socket API Startup Failed: %d\n", WSAGetLastError());
+ return 1;
+ }
- printf("Attempt connect\n");
- fgets(&buff[0], 255, stdin);
- ret = connect(sock, (struct sockaddr *)&server, sizeof(server));
- if (ret < 0) {
- printf("Socket Connection Failed: %d", WSAGetLastError());
- return 1;
- }
+ for (i = 0; i < NUM_CLIENTS; i++) {
+ ClientThreadHandles[i] = CreateThread(
+ NULL,
+ 0,
+ ClientThreadMain,
+ (LPVOID)i,
+ 0,
+ &ClientThreadIDs[i]);
- printf("Connected\n");
+ if (ClientThreadHandles[i] == NULL) {
+ printf("Thread %d failed to spawn\n", i);
+ return 1;
+ }
+ }
- fgets(&buff[0], 255, stdin);
- ret = send(sock, &buff[0], 256, MSG_OOB);
- printf("Sent %d bytes", ret);
-
- fgets(&buff[0], 255, stdin);
-
- return 0;
+ WaitForMultipleObjects(NUM_CLIENTS, ClientThreadHandles, TRUE, INFINITE);
+
+ for (i = 0; i < NUM_CLIENTS; i++) {
+ CloseHandle(ClientThreadHandles[i]);
+ }
+
+ fgets(buff, LENGTH, stdin);
+
+ return 0;
}
Modified: branches/GSoC_2016/lwIP-tcpip/base/applications/network/tcpserver/main.c
URL:
http://svn.reactos.org/svn/reactos/branches/GSoC_2016/lwIP-tcpip/base/appli…
==============================================================================
--- branches/GSoC_2016/lwIP-tcpip/base/applications/network/tcpserver/main.c [iso-8859-1]
(original)
+++ branches/GSoC_2016/lwIP-tcpip/base/applications/network/tcpserver/main.c [iso-8859-1]
Wed Jul 13 21:01:53 2016
@@ -1,73 +1,105 @@
#include <stdio.h>
#include <WinSock2.h>
+#define backlog 4
+#define LENGTH 256
+
int wmain(int argc, LPWSTR argv[]) {
WSADATA wsa;
- SOCKET sock;
- SOCKET accepted;
- struct sockaddr_in server;
- struct sockaddr_in client;
+ SOCKET ListenSock;
+ SOCKET ClientSock;
- int c;
+ struct sockaddr_in ListenAddr;
+ struct sockaddr_in ClientAddr;
+
+ char buff[LENGTH];
+
int ret;
-
- char buff[256];
+ int addrSize;
+ int count;
- memset(&server, 0, sizeof(struct sockaddr_in));
- memset(&client, 0, sizeof(struct sockaddr_in));
+ printf("Server startup\n");
ret = WSAStartup(MAKEWORD(2, 2), &wsa);
if (ret != 0) {
- printf("Windows Socket API Startup Failed: %d", WSAGetLastError());
- exit(1);
+ printf("Windows Socket API Startup Failed: %d\n", WSAGetLastError());
+ fgets(buff, LENGTH, stdin);
+ return 1;
}
- printf("Attempt socket creation\n");
- fgets(&buff[0], 255, stdin);
- sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
- if (sock == INVALID_SOCKET) {
- printf("Socket Creation Failed: %d", WSAGetLastError());
- exit(1);
- }
+ memset(&ListenAddr, 0, sizeof(struct sockaddr_in));
+ ListenAddr.sin_family = AF_INET;
+ ListenAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
+ ListenAddr.sin_port = htons(10000);
- server.sin_family = AF_INET;
- server.sin_addr.s_addr = inet_addr("127.0.0.1");
- server.sin_port = htons(10000);
-
- printf("Attempt bind\n");
- fgets(&buff[0], 255, stdin);
- ret = bind(sock, (struct sockaddr *)&server, sizeof(server));
- if (ret == SOCKET_ERROR) {
- printf("Socket Bind Failed: %d", WSAGetLastError());
- exit(1);
- }
+ ListenSock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+ if (ListenSock == INVALID_SOCKET) {
+ printf("Socket creation failed: %d\n", WSAGetLastError());
+ WSACleanup();
+ fgets(buff, LENGTH, stdin);
+ return 1;
+ }
+ printf("Server listening socket created\n");
- printf("Attempt listen\n");
- fgets(&buff[0], 255, stdin);
- ret = listen(sock, 3);
- if (ret != 0) {
- printf("Socket Listen Failed: %d", WSAGetLastError());
- exit(1);
- }
+ ret = bind(ListenSock, (struct sockaddr *)&ListenAddr, sizeof(ListenAddr));
+ if (ret == SOCKET_ERROR) {
+ printf("Bind failed: %d\n", WSAGetLastError());
+ closesocket(ListenSock);
+ WSACleanup();
+ fgets(buff, LENGTH, stdin);
+ return 1;
+ }
+ printf("Server listening socket bound\n");
- printf("Listening for connections on LOOPBACK port 10000\n");
-
- c = sizeof(struct sockaddr_in);
+ ret = listen(ListenSock, backlog);
+ if (ret == SOCKET_ERROR) {
+ printf("Listen failed: %d\n", WSAGetLastError());
+ closesocket(ListenSock);
+ WSACleanup();
+ fgets(buff, LENGTH, stdin);
+ return 1;
+ }
+ printf("Server listening socket is now listening\n");
- printf("Enter accept loop\n");
- fgets(&buff[0], 255, stdin);
- while(1) {
- accepted = accept(sock, (struct sockaddr *)&client, &c);
- if (accepted == INVALID_SOCKET) {
- printf("Socket Connection Acceptance Failed: %d", WSAGetLastError());
- exit(1);
- } else {
- printf("Socket connection accepted\n");
- ret = recv(accepted, &buff[0], 256, 0);
- printf("Received %d bytes\n", ret);
- printf("Message: %s", &buff[0]);
- }
- }
+ count = 0;
+ // Only a single server handler for now.
+ while (1) {
+ addrSize = sizeof(struct sockaddr_in);
+ memset(buff, 0, sizeof(buff));
+ printf("\nWaiting to accept connection %d\n", count);
+ ClientSock = accept(ListenSock, (struct sockaddr *)&ClientAddr,
&addrSize);
+ if (ClientSock == INVALID_SOCKET) {
+ printf("Accept failed: %d\n", WSAGetLastError());
+ closesocket(ListenSock);
+ WSACleanup();
+ fgets(buff, LENGTH, stdin);
+ return 1;
+ }
+ printf("Connection established to client %d\n", count);
- exit(1);
+ ret = recv(ClientSock, buff, LENGTH, 0);
+ buff[LENGTH - 1] = '\0';
+ printf(" Received %d-byte message from client %d: %s\n", ret, count,
buff);
+
+ ret = send(ClientSock, buff, ret, 0);
+ if (ret == SOCKET_ERROR) {
+ printf("Send failed: %d\n", WSAGetLastError());
+ closesocket(ListenSock);
+ closesocket(ClientSock);
+ WSACleanup();
+ fgets(buff, LENGTH, stdin);
+ return 1;
+ }
+ printf("Message echoed\n");
+
+ closesocket(ClientSock);
+
+ count++;
+ }
+
+ printf("Server exit\n");
+
+ fgets(buff, LENGTH, stdin);
+
+ return 0;
}
Modified: branches/GSoC_2016/lwIP-tcpip/drivers/network/tcpip/address.c
URL:
http://svn.reactos.org/svn/reactos/branches/GSoC_2016/lwIP-tcpip/drivers/ne…
==============================================================================
--- branches/GSoC_2016/lwIP-tcpip/drivers/network/tcpip/address.c [iso-8859-1] (original)
+++ branches/GSoC_2016/lwIP-tcpip/drivers/network/tcpip/address.c [iso-8859-1] Wed Jul 13
21:01:53 2016
@@ -11,6 +11,13 @@
#include <debug.h>
volatile long int PcbCount;
+volatile long int AddrFileCount;
+volatile long int ContextCount;
+
+struct tcp_pcb *PCBList[128];
+PADDRESS_FILE AddrFileList[128];
+PTCP_CONTEXT ContextList[128];
+
typedef struct
{
@@ -197,6 +204,12 @@
InitializeListHead(&AddressListHead);
PcbCount = 0;
+ AddrFileCount = 0;
+ ContextCount = 0;
+
+ RtlZeroMemory(PCBList, sizeof(PCBList));
+ RtlZeroMemory(AddrFileList, sizeof(AddrFileList));
+ RtlZeroMemory(ContextList, sizeof(ContextList));
}
static
@@ -297,8 +310,6 @@
ExFreePoolWithTag(Request, TAG_TCP_REQUEST);
}
- KeReleaseSpinLockFromDpcLevel(&Context->RequestListLock);
-
if (Context->lwip_tcp_pcb != AddressFile->lwip_tcp_pcb)
{
tcp_arg(Context->lwip_tcp_pcb, NULL);
@@ -307,6 +318,8 @@
DPRINT1("\n PCB Count\n", PcbCount);
}
Context->lwip_tcp_pcb = NULL;
+
+ KeReleaseSpinLockFromDpcLevel(&Context->RequestListLock);
Entry = Entry->Flink;
}
@@ -339,14 +352,14 @@
ExFreePoolWithTag(Request, TAG_TCP_REQUEST);
}
- KeReleaseSpinLock(&Context->RequestListLock, OldIrql);
-
if (Context->AddressFile &&
(Context->lwip_tcp_pcb == Context->AddressFile->lwip_tcp_pcb))
{
Context->AddressFile->lwip_tcp_pcb = NULL;
}
Context->lwip_tcp_pcb = NULL;
+
+ KeReleaseSpinLock(&Context->RequestListLock, OldIrql);
return;
default :
@@ -476,9 +489,9 @@
while (Entry != Head)
{
Context = CONTAINING_RECORD(Entry, TCP_CONTEXT, ListEntry);
+ KeAcquireSpinLockAtDpcLevel(&Context->RequestListLock);
if (Context->TcpState == TCP_STATE_LISTENING)
{
- KeAcquireSpinLockAtDpcLevel(&Context->RequestListLock);
Context->lwip_tcp_pcb = newpcb;
tcp_err(Context->lwip_tcp_pcb, lwip_tcp_err_callback);
@@ -534,6 +547,7 @@
IoCompleteRequest(Irp, IO_NETWORK_INCREMENT);
return ERR_OK;
}
+ KeReleaseSpinLockFromDpcLevel(&Context->RequestListLock);
Entry = Entry->Flink;
}
@@ -674,11 +688,12 @@
}*/
Context = (PTCP_CONTEXT)arg;
+ KeAcquireSpinLock(&Context->RequestListLock, &OldIrql);
if (!(Context->TcpState & TCP_STATE_RECEIVING)) {
DPRINT1("Receive callback on connection that is not currently receiving\n");
+ KeReleaseSpinLock(&Context->RequestListLock, OldIrql);
return ERR_ARG;
}
- KeAcquireSpinLock(&Context->RequestListLock, &OldIrql);
Head = &Context->RequestListHead;
Entry = Head->Flink;
Irp = NULL;
@@ -879,13 +894,13 @@
return ERR_ARG;
}
Entry = RemoveHeadList(Head);
- KeReleaseSpinLock(&Context->RequestListLock, OldIrql);
Request = CONTAINING_RECORD(Entry, TCP_REQUEST, ListEntry);
Irp = Request->PendingIrp;
if (!Irp)
{
DPRINT1("Callback on cancelled IRP\n");
ExFreePoolWithTag(Request, TAG_TCP_REQUEST);
+ KeReleaseSpinLock(&Context->RequestListLock, OldIrql);
return ERR_ABRT;
}
IoSetCancelRoutine(Irp, NULL);
@@ -893,14 +908,18 @@
if (Context->TcpState != TCP_STATE_CONNECTING)
{
DPRINT1("Invalid TCP state: %d\n", Context->TcpState);
- lwip_err = ERR_ABRT;
- goto FINISH;
+ ExFreePoolWithTag(Request, TAG_TCP_REQUEST);
+ Irp->IoStatus.Status = STATUS_SUCCESS;
+ IoCompleteRequest(Irp, IO_NETWORK_INCREMENT);
+ return ERR_ABRT;
}
Context->TcpState = TCP_STATE_CONNECTED;
+
+ KeReleaseSpinLock(&Context->RequestListLock, OldIrql);
+
lwip_err = ERR_OK;
-FINISH:
ExFreePoolWithTag(Request, TAG_TCP_REQUEST);
Irp->IoStatus.Status = STATUS_SUCCESS;
@@ -1126,6 +1145,7 @@
/* Lock the global address list */
KeAcquireSpinLock(&AddressListLock, &OldIrql);
+ KeAcquireSpinLockAtDpcLevel(&AddressFile->ContextListLock);
InterlockedDecrement(&AddressFile->RefCount);
if (AddressFile->RefCount != 0)
@@ -1147,6 +1167,7 @@
{
DPRINT1("Calling close on TCP address with open contexts\n");
// Should never happen due to how callers are written.
+ KeReleaseSpinLockFromDpcLevel(&AddressFile->ContextListLock);
KeReleaseSpinLock(&AddressListLock, OldIrql);
return STATUS_INVALID_PARAMETER;
}
@@ -1189,11 +1210,13 @@
/* Remove from the list and free the structure */
RemoveEntryList(&AddressFile->ListEntry);
+ RemoveEntityInstance(&AddressFile->Instance);
+
+ KeReleaseSpinLockFromDpcLevel(&AddressFile->ContextListLock);
+
+ ExFreePoolWithTag(AddressFile, TAG_ADDRESS_FILE);
+
KeReleaseSpinLock(&AddressListLock, OldIrql);
-
- RemoveEntityInstance(&AddressFile->Instance);
-
- ExFreePoolWithTag(AddressFile, TAG_ADDRESS_FILE);
return Status;
}
@@ -1212,21 +1235,28 @@
PIO_STACK_LOCATION IrpSp;
KIRQL OldIrql;
+ NTSTATUS Status;
+
+ AddressFile = Context->AddressFile;
+
+ KeAcquireSpinLock(&AddressFile->ContextListLock, &OldIrql);
+ KeAcquireSpinLockAtDpcLevel(&Context->RequestListLock);
if (Context->Protocol != IPPROTO_TCP)
{
DPRINT1("Invalid protocol\n");
+ KeReleaseSpinLockFromDpcLevel(&Context->RequestListLock);
+ KeReleaseSpinLock(&AddressFile->ContextListLock, OldIrql);
return STATUS_INVALID_PARAMETER;
}
if (!(Context->TcpState & TCP_STATE_DISASSOCIATED))
{
DPRINT1("Context retains association\n");
+ KeReleaseSpinLockFromDpcLevel(&Context->RequestListLock);
+ KeReleaseSpinLock(&AddressFile->ContextListLock, OldIrql);
return STATUS_UNSUCCESSFUL;
}
- KeAcquireSpinLock(&Context->RequestListLock, &OldIrql);
-
- AddressFile = Context->AddressFile;
if (Context->lwip_tcp_pcb == AddressFile->lwip_tcp_pcb)
{
Context->lwip_tcp_pcb = NULL;
@@ -1254,7 +1284,8 @@
if (lwip_err != ERR_OK)
{
DPRINT1("lwIP tcp_close error: %d", lwip_err);
- KeReleaseSpinLock(&Context->RequestListLock, OldIrql);
+ KeReleaseSpinLockFromDpcLevel(&Context->RequestListLock);
+ KeReleaseSpinLock(&AddressFile->ContextListLock, OldIrql);
return STATUS_UNSUCCESSFUL;
}
}
@@ -1271,28 +1302,36 @@
if (IrpSp->FileObject->FsContext != Context)
{
DPRINT1("IRP context mismatch\n");
- KeReleaseSpinLock(&Context->RequestListLock, OldIrql);
+ KeReleaseSpinLockFromDpcLevel(&Context->RequestListLock);
+ KeReleaseSpinLock(&AddressFile->ContextListLock, OldIrql);
return STATUS_UNSUCCESSFUL;
}
DPRINT1("Unexpected outstanding request on context\n");
- KeReleaseSpinLock(&Context->RequestListLock, OldIrql);
+ KeReleaseSpinLockFromDpcLevel(&Context->RequestListLock);
+ KeReleaseSpinLock(&AddressFile->ContextListLock, OldIrql);
return STATUS_UNSUCCESSFUL;
}
Entry = Entry->Flink;
ExFreePoolWithTag(Request, TAG_TCP_REQUEST);
}
- KeReleaseSpinLock(&Context->RequestListLock, OldIrql);
+ KeReleaseSpinLockFromDpcLevel(&Context->RequestListLock);
ExFreePoolWithTag(Context, TAG_TCP_CONTEXT);
if (AddressFile->ContextCount == 0)
{
- return TcpIpCloseAddress(AddressFile);
- }
-
- return STATUS_SUCCESS;
+ Status = TcpIpCloseAddress(AddressFile);
+ }
+ else
+ {
+ Status = STATUS_SUCCESS;
+ }
+
+ KeReleaseSpinLock(&AddressFile->ContextListLock, OldIrql);
+
+ return Status;
}
static
@@ -1393,14 +1432,17 @@
}
Context = IrpSp->FileObject->FsContext;
+ KeAcquireSpinLock(&Context->RequestListLock, &OldIrql);
if (Context->AddressFile->Protocol != IPPROTO_TCP)
{
DPRINT1("Received TDI_CONNECT for a non-TCP protocol\n");
+ KeReleaseSpinLock(&Context->RequestListLock, OldIrql);
return STATUS_INVALID_ADDRESS;
}
if (Context->TcpState != TCP_STATE_BOUND)
{
DPRINT1("Connecting on address that's not bound\n");
+ KeReleaseSpinLock(&Context->RequestListLock, OldIrql);
return STATUS_INVALID_ADDRESS;
}
@@ -1420,17 +1462,20 @@
case (ERR_VAL) :
{
DPRINT1("lwip ERR_VAL\n");
+ KeReleaseSpinLock(&Context->RequestListLock, OldIrql);
return STATUS_INVALID_PARAMETER;
}
case (ERR_ISCONN) :
{
DPRINT1("lwip ERR_ISCONN\n");
+ KeReleaseSpinLock(&Context->RequestListLock, OldIrql);
return STATUS_CONNECTION_ACTIVE;
}
case (ERR_RTE) :
{
/* several errors look right here */
DPRINT1("lwip ERR_RTE\n");
+ KeReleaseSpinLock(&Context->RequestListLock, OldIrql);
return STATUS_NETWORK_UNREACHABLE;
}
case (ERR_BUF) :
@@ -1438,22 +1483,24 @@
/* use correct error once NDIS errors are included
this return value means local port unavailable */
DPRINT1("lwip ERR_BUF\n");
+ KeReleaseSpinLock(&Context->RequestListLock, OldIrql);
return STATUS_ADDRESS_ALREADY_EXISTS;
}
case (ERR_USE) :
{
/* STATUS_CONNECTION_ACTIVE maybe? */
DPRINT1("lwip ERR_USE\n");
+ KeReleaseSpinLock(&Context->RequestListLock, OldIrql);
return STATUS_ADDRESS_ALREADY_EXISTS;
}
case (ERR_MEM) :
{
DPRINT1("lwip ERR_MEM\n");
+ KeReleaseSpinLock(&Context->RequestListLock, OldIrql);
return STATUS_NO_MEMORY;
}
case (ERR_OK) :
{
- KeAcquireSpinLock(&Context->RequestListLock, &OldIrql);
PrepareIrpForCancel(
Irp,
CancelRequestRoutine,
@@ -1468,6 +1515,7 @@
{
/* unknown return value */
DPRINT1("lwip unknown return code\n");
+ KeReleaseSpinLock(&Context->RequestListLock, OldIrql);
return STATUS_NOT_IMPLEMENTED;
}
}
@@ -1489,21 +1537,6 @@
KIRQL OldIrql;
IrpSp = IoGetCurrentIrpStackLocation(Irp);
-
- if (IrpSp->FileObject->FsContext2 != (PVOID)TDI_CONNECTION_FILE)
- {
- DPRINT1("Associating something that is not a TDI_CONNECTION_FILE\n");
- Status = STATUS_INVALID_PARAMETER;
- goto LEAVE;
- }
- Context = IrpSp->FileObject->FsContext;
-
- if (Context->lwip_tcp_pcb || Context->Protocol != IPPROTO_TCP)
- {
- DPRINT1("Connection context is not a new TCP context\n");
- Status = STATUS_INVALID_PARAMETER;
- goto LEAVE;
- }
/* Get address file */
RequestInfo = (PTDI_REQUEST_KERNEL_ASSOCIATE)&IrpSp->Parameters;
@@ -1528,20 +1561,35 @@
return STATUS_INVALID_PARAMETER;
}
AddressFile = FileObject->FsContext;
+ KeAcquireSpinLock(&AddressFile->ContextListLock, &OldIrql);
if (AddressFile->Protocol != IPPROTO_TCP)
{
DPRINT1("TCP socket association with non-TCP handle\n");
+ KeReleaseSpinLock(&AddressFile->ContextListLock, OldIrql);
ObDereferenceObject(FileObject);
return STATUS_INVALID_PARAMETER;
}
-
if (AddressFile->Address.in_addr == 0)
{
// TODO: should really look through address file list for an interface
AddressFile->Address.in_addr = 0x0100007f;
}
- KeAcquireSpinLock(&AddressFile->ContextListLock, &OldIrql);
+ if (IrpSp->FileObject->FsContext2 != (PVOID)TDI_CONNECTION_FILE)
+ {
+ DPRINT1("Associating something that is not a TDI_CONNECTION_FILE\n");
+ KeReleaseSpinLock(&AddressFile->ContextListLock, OldIrql);
+ return STATUS_INVALID_PARAMETER;
+ }
+ Context = IrpSp->FileObject->FsContext;
+ KeAcquireSpinLockAtDpcLevel(&Context->RequestListLock);
+ if (Context->lwip_tcp_pcb || Context->Protocol != IPPROTO_TCP)
+ {
+ DPRINT1("Connection context is not a new TCP context\n");
+ KeReleaseSpinLockFromDpcLevel(&Context->RequestListLock);
+ KeReleaseSpinLock(&AddressFile->ContextListLock, OldIrql);
+ return STATUS_INVALID_PARAMETER;
+ }
Context->AddressFile = AddressFile;
InsertTailList(&AddressFile->ContextListHead,
@@ -1596,6 +1644,7 @@
Context->TcpState = TCP_STATE_BOUND;
LEAVE:
+ KeReleaseSpinLockFromDpcLevel(&Context->RequestListLock);
KeReleaseSpinLock(&AddressFile->ContextListLock, OldIrql);
return Status;
@@ -1625,14 +1674,21 @@
Context = IrpSp->FileObject->FsContext;
AddressFile = Context->AddressFile;
+ KeAcquireSpinLock(&AddressFile->ContextListLock, &OldIrql);
+ KeAcquireSpinLockAtDpcLevel(&Context->RequestListLock);
+
if (AddressFile->Protocol != IPPROTO_TCP)
{
DPRINT1("Received TDI_DISASSOCIATE_ADDRESS for non-TCP protocol\n");
+ KeReleaseSpinLockFromDpcLevel(&Context->RequestListLock);
+ KeReleaseSpinLock(&AddressFile->ContextListLock, OldIrql);
return STATUS_INVALID_ADDRESS;
}
if (Context->Protocol != IPPROTO_TCP)
{
DPRINT1("Address File and Context have mismatching protocols\n");
+ KeReleaseSpinLockFromDpcLevel(&Context->RequestListLock);
+ KeReleaseSpinLock(&AddressFile->ContextListLock, OldIrql);
return STATUS_INVALID_ADDRESS;
}
@@ -1641,7 +1697,6 @@
Context->lwip_tcp_pcb = NULL;
}
- KeAcquireSpinLock(&Context->RequestListLock, &OldIrql);
if (!(IsListEmpty(&Context->RequestListHead)))
{
DPRINT1("Disassociating context with outstanding requests\n");
@@ -1658,12 +1713,12 @@
}
}
}
- KeReleaseSpinLock(&Context->RequestListLock, OldIrql);
-
- KeAcquireSpinLock(&AddressFile->ContextListLock, &OldIrql);
+
RemoveEntryList(&Context->ListEntry);
AddressFile->ContextCount--;
Context->TcpState |= TCP_STATE_DISASSOCIATED;
+
+ KeReleaseSpinLockFromDpcLevel(&Context->RequestListLock);
KeReleaseSpinLock(&AddressFile->ContextListLock, OldIrql);
return STATUS_SUCCESS;
@@ -1691,16 +1746,18 @@
}
/* Get context file */
Context = IrpSp->FileObject->FsContext;
+ AddressFile = Context->AddressFile;
+ KeAcquireSpinLock(&AddressFile->ContextListLock, &OldIrql);
+ KeAcquireSpinLockAtDpcLevel(&Context->RequestListLock);
if (!(Context->TcpState & TCP_STATE_BOUND))
{
DPRINT1("Received TDI_LISTEN for a context that has not been associated\n");
// TODO: better return code
+ KeReleaseSpinLockFromDpcLevel(&Context->RequestListLock);
+ KeReleaseSpinLock(&AddressFile->ContextListLock, OldIrql);
return STATUS_UNSUCCESSFUL;
}
- AddressFile = Context->AddressFile;
-
- KeAcquireSpinLock(&AddressFile->ContextListLock, &OldIrql);
if (AddressFile->ContextListHead.Flink == &Context->ListEntry)
{
lpcb = tcp_listen(Context->lwip_tcp_pcb);
@@ -1712,22 +1769,22 @@
either INVALID_ADDRESS or NO_MEMORY
if SO_REUSE is enabled in lwip options */
DPRINT1("lwip tcp_listen error\n");
+ KeReleaseSpinLockFromDpcLevel(&Context->RequestListLock);
KeReleaseSpinLock(&AddressFile->ContextListLock, OldIrql);
return STATUS_INVALID_ADDRESS;
}
tcp_arg(lpcb, AddressFile);
tcp_accept(lpcb, lwip_tcp_accept_callback);
}
- KeReleaseSpinLock(&AddressFile->ContextListLock, OldIrql);
-
- KeAcquireSpinLock(&Context->RequestListLock, &OldIrql);
+
PrepareIrpForCancel(
Irp,
CancelRequestRoutine,
TCP_REQUEST_CANCEL_MODE_CLOSE,
TCP_REQUEST_PENDING_GENERAL);
Context->TcpState = TCP_STATE_LISTENING;
- KeReleaseSpinLock(&Context->RequestListLock, OldIrql);
+ KeReleaseSpinLockFromDpcLevel(&Context->RequestListLock);
+ KeReleaseSpinLock(&AddressFile->ContextListLock, OldIrql);
return STATUS_PENDING;
}
@@ -1757,16 +1814,19 @@
return STATUS_INVALID_PARAMETER;
}
Context = IrpSp->FileObject->FsContext;
+ KeAcquireSpinLock(&Context->RequestListLock, &OldIrql);
if (!(Context->TcpState & (TCP_STATE_ACCEPTED|TCP_STATE_CONNECTED)))
{
DPRINT1("Invalid TCP state: %d\n", Context->TcpState);
+ KeReleaseSpinLock(&Context->RequestListLock, OldIrql);
// TODO: better return code
return STATUS_UNSUCCESSFUL;
}
if (!Irp->MdlAddress)
{
DPRINT1("TcpIpSend Empty\n");
+ KeReleaseSpinLock(&Context->RequestListLock, OldIrql);
return STATUS_INVALID_PARAMETER;
}
NdisQueryBuffer(Irp->MdlAddress, &Buffer, &Len);
@@ -1774,10 +1834,9 @@
if (!Context->lwip_tcp_pcb)
{
DPRINT1("TcpIpSend with no lwIP tcp_pcb\n");
+ KeReleaseSpinLock(&Context->RequestListLock, OldIrql);
return STATUS_INVALID_PARAMETER;
}
-
- KeAcquireSpinLock(&Context->RequestListLock, &OldIrql);
Head = &Context->RequestListHead;
Entry = Head->Flink;
@@ -1853,14 +1912,13 @@
return STATUS_INVALID_PARAMETER;
}
Context = IrpSp->FileObject->FsContext;
+ KeAcquireSpinLock(&Context->RequestListLock, &OldIrql);
//DPRINT1("Receive Context Address: %08x\n", Context);
//DPRINT1("Receive Address File Address: %08x\n", Context->AddressFile);
if (Context->TcpState & (TCP_STATE_CONNECTED|TCP_STATE_ACCEPTED))
{
RequestInfo = (PTDI_REQUEST_KERNEL_RECEIVE)&IrpSp->Parameters;
//DPRINT1("\n Request Length = %d\n", RequestInfo->ReceiveLength);
-
- KeAcquireSpinLock(&Context->RequestListLock, &OldIrql);
PrepareIrpForCancel(
Irp,
@@ -1878,6 +1936,7 @@
KeReleaseSpinLock(&Context->RequestListLock, OldIrql);
return STATUS_PENDING;
}
+ KeReleaseSpinLock(&Context->RequestListLock, OldIrql);
DPRINT1("Invalid TCP state: %d\n", Context->TcpState);
// TODO: better return error
return STATUS_UNSUCCESSFUL;