Beispiel #1
0
        static IEnumerator<Int32> HandleClient(AsyncEnumerator ae,
                                               ServerState server,
                                               ClientState client,
                                               TcpClient tcpRecv,
                                               TcpClient tcpSend,
                                               BufferWrapper bw,
                                               FilterFunc filterFunc)
        {
            // add the client to the clients list
            {
                server.clientsMutex.BeginRegion(SyncGateMode.Exclusive, ae.End());
                yield return 1;
                var mutexResult = ae.DequeueAsyncResult();
                {
                    if (!server.clients.ContainsKey(client.localtcp))
                    {
                        server.clients[client.localtcp] = client;
                    }
                }
                server.clientsMutex.EndRegion(mutexResult);
            }

            Socket sockRecv = tcpRecv.Client;
            Socket sockSend = tcpSend.Client;
            bool wantDisconnect = false;
            int len = 0;
            while (true)
            {
                // read message
                try
                {
                    // resize buffer if needed so that it has initialbuffersize spaces at the end
                    if((bw.buffer.Length - len) < server.settings.initialbuffersize)
                    {
                        Array.Resize(ref bw.buffer, len + server.settings.initialbuffersize);
                    }

                    sockRecv.BeginReceive(bw.buffer, len, server.settings.initialbuffersize, SocketFlags.None, ae.End(), null);
                }
                catch (Exception)
                {
                    break;
                }

                yield return 1;

                try
                {
                    int tmplen = sockRecv.EndReceive(ae.DequeueAsyncResult());

                    if (tmplen == 0)
                    {
                        break;
                    }
                    else
                    {
                        len += tmplen;
                    }
                }
                catch (Exception)
                {
                    break;
                }

                // filter the packets here
                switch (filterFunc(client, bw.buffer, len))
                {
                    case FilterIntent.Buffer:
                        break;

                    case FilterIntent.Accept:
                        int sent = 0;
                        while(sent < len)
                        {
                            // echo the data back to the client
                            try
                            {
                                sockSend.BeginSend(bw.buffer, sent, len-sent, SocketFlags.None, ae.End(), null);
                            }
                            catch (Exception)
                            {
                                wantDisconnect = true;
                                break;
                            }
                            yield return 1;

                            try
                            {
                                sent += sockSend.EndSend(ae.DequeueAsyncResult());
                            }
                            catch (Exception)
                            {
                                wantDisconnect = true;
                                break;
                            }
                        }
                        len = 0;
                        break;

                    case FilterIntent.Drop:
                        len = 0;
                        break;

                    case FilterIntent.Disconnect:
                        wantDisconnect = true;
                        break;
                }

                if(wantDisconnect)
                    break;
            }

            // remove the client from the list
            {
                server.clientsMutex.BeginRegion(SyncGateMode.Exclusive, ae.End());
                yield return 1;
                var mutexResult = ae.DequeueAsyncResult();
                {
                    if (server.clients.ContainsKey(client.localtcp))
                    {
                        var removed = server.clients.Remove(client.localtcp);
                        Console.WriteLine("Client disconnected {0} - {1}", client.localtcp.Client.RemoteEndPoint, removed);

                        // dont forget to dispose it
                        tcpRecv.Close();
                        tcpSend.Close();
                    }
                }
                server.clientsMutex.EndRegion(mutexResult);
            }
        }
Beispiel #2
0
        static IEnumerator<Int32> ServerConnectRemote(AsyncEnumerator ae, ServerState server, IPEndPoint ipe, TcpClient local)
        {
            // establish a client proxy -> real server connection

            var remote = new TcpClient(ipe.AddressFamily);
            var settings = server.settings;
            remote.NoDelay = true;
            remote.LingerState.Enabled = false;

            remote.BeginConnect(IPAddress.Parse(settings.addressforward), settings.portforward, ae.End(), ae);
            yield return 1;

            try
            {
                remote.EndConnect(ae.DequeueAsyncResult());
            }
            catch (SocketException)
            {
                Console.WriteLine("A client failed to connect, has the real server started?");
                local.Close();
                remote.Close();
                remote = null;
            }

            if(remote != null)
            {
                var bufParam = new ClientBufferParam();

                {
                    server.bufferPoolMutex.BeginRegion(SyncGateMode.Exclusive, ae.End());
                    yield return 1;
                    var res = ae.DequeueAsyncResult();
                    server.AllocBuffer(ae, bufParam);
                    server.bufferPoolMutex.EndRegion(res);
                }

                {
                    var newClientState = new ClientState(local, remote);
                    var remoteAe = new AsyncEnumerator();
                    var localAe = new AsyncEnumerator();
                    var bw1 = new BufferWrapper(bufParam.sendbuffer);
                    var bw2 = new BufferWrapper(bufParam.recvbuffer);
                    localAe.BeginExecute(HandleClient(localAe, server, newClientState, local, remote, bw1, server.filterSend), ae.End(), localAe);
                    remoteAe.BeginExecute(HandleClient(remoteAe, server, newClientState, remote, local, bw2, server.filterRecv), ae.End(), remoteAe);

                    Console.WriteLine("Client Connected {0}", local.Client.RemoteEndPoint);

                    yield return 2;
                    for (int x = 0; x < 2; x++)
                    {
                        IAsyncResult ar = ae.DequeueAsyncResult();
                        ((AsyncEnumerator)ar.AsyncState).EndExecute(ar);
                    }
                    bufParam.sendbuffer = bw1.buffer;
                    bufParam.recvbuffer = bw2.buffer;
                }

                {
                    server.bufferPoolMutex.BeginRegion(SyncGateMode.Exclusive, ae.End());
                    yield return 1;
                    var res = ae.DequeueAsyncResult();
                    server.FreeBuffer(ae, bufParam);
                    server.bufferPoolMutex.EndRegion(res);
                }
            }
        }