Beispiel #1
0
        private void DoClient()
        {
            string lastRequest = null;

            try
            {
                DateTime lastRequestWriteUtc = DateTime.MinValue;
                int      repeated            = 0;

                var buffer = new byte[BUFFER_LENGTH];
                int read;

                client.SendBufferSize    = SEND_BUFFER_LENGTH;
                client.ReceiveBufferSize = RECEIVE_BUFFER_LENGTH;

                HttpStream            stream = new HttpStream(client.GetStream());
                HttpStream.HttpHeader header;

                while (client.Connected)
                {
                    if ((read = stream.ReadHeader(buffer, 0, out header)) == 0)
                    {
                        return;
                    }

                    try
                    {
                        do
                        {
                            read = stream.Read(buffer, 0, BUFFER_LENGTH);
                        }while (read > 0);

                        var request = (HttpStream.HttpRequestHeader)header;
                        var source  = Path.Combine(root, Util.FileName.FromAssetRequest(request.Location));

                        if (RequestHeaderReceived != null)
                        {
                            RequestHeaderReceived(this, request);
                        }

                        bool retry = false;
                        do
                        {
                            var fi = new FileInfo(source);
                            if (fi.Exists)
                            {
                                if (!retry && lastRequest == request.Location)
                                {
                                    if (lastRequestWriteUtc != fi.LastWriteTimeUtc)
                                    {
                                        lastRequestWriteUtc = fi.LastWriteTimeUtc;
                                        repeated            = 0;
                                    }
                                    else if (++repeated == 2)
                                    {
                                        //saved data is likely corrupted
                                        if (RequestRepeated != null)
                                        {
                                            RequestRepeated(this, request.Location);
                                        }
                                    }
                                }
                                else
                                {
                                    lastRequest         = request.Location;
                                    repeated            = 0;
                                    lastRequestWriteUtc = fi.LastWriteTimeUtc;
                                    retry = false;
                                }

                                bool headers = true;
                                using (var r = File.Open(source, FileMode.Open, FileAccess.Read, FileShare.ReadWrite | FileShare.Delete))
                                {
                                    do
                                    {
                                        read = r.Read(buffer, 0, BUFFER_LENGTH);
                                        if (read > 0)
                                        {
                                            int offset = 0;

                                            if (headers)
                                            {
                                                headers = false;
                                                var h = BitConverter.ToUInt32(buffer, 0);
                                                if (h == HEADER_HTTP_UPPER || h == HEADER_HTTP_LOWER)
                                                {
                                                    //already has headers

                                                    int n = 0;
                                                    for (var i = 0; i < read; i++)
                                                    {
                                                        switch (buffer[i])
                                                        {
                                                        case (byte)'\r':
                                                            break;

                                                        case (byte)'\n':
                                                            if (++n == 2)
                                                            {
                                                                stream.Write(buffer, 0, offset = i + 1);
                                                                i = read;
                                                            }
                                                            break;

                                                        default:
                                                            n = 0;
                                                            break;
                                                        }
                                                    }
                                                }
                                                else
                                                {
                                                    //warning: only full files can have empty headers - checksum required for patches
                                                    WriteHeader(stream, r.Length);
                                                    stream.Write(buffer, 0, read);
                                                }
                                            }

                                            while (offset < read)
                                            {
                                                int c = read - offset;
                                                if (c > SEND_BUFFER_LENGTH)
                                                {
                                                    c = SEND_BUFFER_LENGTH;
                                                }
                                                stream.Write(buffer, offset, c);
                                                offset += c;
                                            }
                                        }
                                    }while (read > 0);
                                }
                            }
                            else
                            {
                                if (retry)
                                {
                                    retry = false;
                                }
                                else
                                {
                                    if (FileNotFound != null)
                                    {
                                        FileNotFoundEventArgs e = new FileNotFoundEventArgs(request.Location);
                                        FileNotFound(this, e);
                                        if (e.Retry)
                                        {
                                            retry = true;
                                        }
                                    }
                                }

                                //sending a bad response will cause GW2 to try different versions:
                                //patch (baseId/fileId) > full file compressed (0/fileId/compressed) > full file (0/fileId)
                                if (!retry)
                                {
                                    WriteHeader(stream, 404, "Not Found");
                                }
                            }
                        }while (retry);

                        var keepAlive = request.Headers[HttpRequestHeader.Connection];
                        if (keepAlive == null || !keepAlive.Equals("keep-alive", StringComparison.OrdinalIgnoreCase))
                        {
                            return;
                        }
                    }
                    finally
                    {
                    }
                }
            }
            catch (Exception e)
            {
                if (Error != null)
                {
                    Error(this, e);
                }
            }
            finally
            {
                server.ActiveStateChanged -= server_ActiveStateChanged;

                if (client != null)
                {
                    client.Close();
                }

                if (Closed != null)
                {
                    Closed(this, EventArgs.Empty);
                }
            }
        }