Statistics
| Branch: | Tag: | Revision:

root / Server / UPacketHandlers.pas @ 13:c78b5eafa10e

History | View | Annotate | Download (7 kB)

1
(*
2
 * CDDL HEADER START
3
 *
4
 * The contents of this file are subject to the terms of the
5
 * Common Development and Distribution License, Version 1.0 only
6
 * (the "License").  You may not use this file except in compliance
7
 * with the License.
8
 *
9
 * You can obtain a copy of the license at
10
 * http://www.opensource.org/licenses/cddl1.php.
11
 * See the License for the specific language governing permissions
12
 * and limitations under the License.
13
 *
14
 * When distributing Covered Code, include this CDDL HEADER in each
15
 * file and include the License file at
16
 * http://www.opensource.org/licenses/cddl1.php.  If applicable,
17
 * add the following below this CDDL HEADER, with the fields enclosed
18
 * by brackets "[]" replaced with your own identifying * information:
19
 *      Portions Copyright [yyyy] [name of copyright owner]
20
 *
21
 * CDDL HEADER END
22
 *
23
 *
24
 *      Portions Copyright 2007 Andreas Schneider
25
 *)
26
unit UPacketHandlers;
27
28
interface
29
30
uses
31
  Classes, SysUtils, dzlib, math, UConfig, UNetState, UEnhancedMemoryStream, UEnums,
32
  ULinkedList, URegions;
33
34
type
35
  TPacketProcessor = procedure(ABuffer: TEnhancedMemoryStream; ANetState: TNetState);
36
  TPacketProcessorMethod = procedure(ABuffer: TEnhancedMemoryStream; ANetState: TNetState) of object;
37
38
  { TPacketHandler }
39
40
  TPacketHandler = class(TObject)
41
    constructor Create(ALength: Cardinal; APacketProcessor: TPacketProcessor); overload;
42
    constructor Create(ALength: Cardinal; APacketProcessorMethod: TPacketProcessorMethod); overload;
43
    procedure Process(ABuffer: TEnhancedMemoryStream; ANetState: TNetState);
44
  protected
45
    FLength: Cardinal;
46
    FPacketProcessor: TPacketProcessor;
47
    FPacketProcessorMethod: TPacketProcessorMethod;
48
  published
49
    property PacketLength: Cardinal read FLength;
50
  end;
51
52
var
53
  PacketHandlers: array[0..$FF] of TPacketHandler;
54
  
55
function ValidateAccess(ANetState: TNetState; ALevel: TAccessLevel): Boolean; overload;
56
function ValidateAccess(ANetState: TNetState; ALevel: TAccessLevel; AX, AY: Cardinal): Boolean; overload;
57
procedure RegisterPacketHandler(AID: Byte; APacketHandler: TPacketHandler);
58
59
implementation
60
61
uses
62
  UCEDServer, UPackets, UConnectionHandling, UAdminHandling, UClientHandling;
63
64
function ValidateAccess(ANetState: TNetState; ALevel: TAccessLevel): Boolean;
65
begin
66
  Result := (ANetState.Account <> nil) and (ANetState.Account.AccessLevel >= ALevel);
67
end;
68
69
function ValidateAccess(ANetState: TNetState; ALevel: TAccessLevel; AX, AY: Cardinal): Boolean;
70
var
71
  i,j: Word;
72
  region: TRegion;
73
  rect: TRect;
74
begin
75
  if not ValidateAccess(ANetState, ALevel) then Exit(False);
76
  if (ANetState.Account.Regions.Count = 0) or
77
    (ANetState.Account.AccessLevel >= alAdministrator) then Exit(True); //no restrictions
78
79
  Result := False;
80
  for i := 0 to ANetState.Account.Regions.Count - 1 do
81
  begin
82
    region := Config.Regions.Find(ANetState.Account.Regions[i]);
83
    if region <> nil then
84
    begin
85
      for j := 0 to region.Areas.Count - 1 do
86
      begin
87
        rect := region.Areas.Rects[j];
88
        if InRange(AX, rect.Left, rect.Right) and
89
          InRange(AY, rect.Top, rect.Bottom) then
90
          Exit(True);
91
      end;
92
    end;
93
  end;
94
end;
95
96
procedure RegisterPacketHandler(AID: Byte; APacketHandler: TPacketHandler);
97
begin
98
  if Assigned(PacketHandlers[AID]) then FreeAndNil(PacketHandlers[AID]);
99
  PacketHandlers[AID] := APacketHandler;
100
end;
101
102
{ TPacketHandler }
103
104
constructor TPacketHandler.Create(ALength: Cardinal; APacketProcessor: TPacketProcessor);
105
begin
106
  inherited Create;
107
  FLength := ALength;
108
  FPacketProcessor := APacketProcessor;
109
  FPacketProcessorMethod := nil;
110
end;
111
112
constructor TPacketHandler.Create(ALength: Cardinal;
113
  APacketProcessorMethod: TPacketProcessorMethod);
114
begin
115
  inherited Create;
116
  FLength := ALength;
117
  FPacketProcessor := nil;
118
  FPacketProcessorMethod := APacketProcessorMethod;
119
end;
120
121
procedure TPacketHandler.Process(ABuffer: TEnhancedMemoryStream; ANetState: TNetState);
122
begin
123
  if Assigned(FPacketProcessor) then
124
    FPacketProcessor(ABuffer, ANetState)
125
  else if Assigned(FPacketProcessorMethod) then
126
    FPacketProcessorMethod(ABuffer, ANetState);
127
end;
128
129
procedure OnCompressedPacket(ABuffer: TEnhancedMemoryStream; ANetState: TNetState);
130
var
131
  uncompStream: TEnhancedMemoryStream;
132
  uncompBuffer: TDecompressionStream;
133
  targetSize: Cardinal;
134
  packetID: Byte;
135
begin
136
  targetSize := ABuffer.ReadCardinal;
137
  uncompBuffer := TDecompressionStream.Create(ABuffer);
138
  uncompStream := TEnhancedMemoryStream.Create;
139
  try
140
    uncompStream.CopyFrom(uncompBuffer, targetSize);
141
    uncompStream.Position := 0;
142
    packetID := uncompStream.ReadByte;
143
    if PacketHandlers[packetID] <> nil then
144
    begin
145
      if PacketHandlers[PacketID].PacketLength = 0 then
146
        uncompStream.Position := uncompStream.Position + 4;
147
      uncompStream.Lock(uncompStream.Position, uncompStream.Size - uncompStream.Position);
148
      PacketHandlers[PacketID].Process(uncompStream, ANetState);
149
      uncompStream.Unlock;
150
    end else
151
    begin
152
      Writeln(TimeStamp, 'Dropping client due to unknown packet: ', ANetState.Socket.PeerAddress);
153
      ANetState.ReceiveQueue.Clear;
154
      CEDServerInstance.Disconnect(ANetState.Socket);
155
    end;
156
  finally
157
    if uncompBuffer <> nil then uncompBuffer.Free;
158
    if uncompStream <> nil then uncompStream.Free;
159
  end;
160
end;
161
162
procedure OnRequestBlocksPacket(ABuffer: TEnhancedMemoryStream; ANetState: TNetState);
163
var
164
  coords: TBlockCoordsArray;
165
begin
166
  if not ValidateAccess(ANetState, alView) then Exit;
167
  SetLength(coords, (ABuffer.Size - ABuffer.Position) div SizeOf(TBlockCoords));
168
  ABuffer.Read(coords[0], Length(coords) * SizeOf(TBlockCoords));
169
  CEDServerInstance.SendPacket(ANetState, TCompressedPacket.Create(TBlockPacket.Create(coords, ANetState)));
170
end;
171
172
procedure OnFreeBlockPacket(ABuffer: TEnhancedMemoryStream; ANetState: TNetState);
173
var
174
  x, y: Word;
175
  blockSubscriptions: TLinkedList;
176
begin
177
  if not ValidateAccess(ANetState, alView) then Exit;
178
  x := ABuffer.ReadWord;
179
  y := ABuffer.ReadWord;
180
  blockSubscriptions := CEDServerInstance.Landscape.BlockSubscriptions[X, Y];
181
  if blockSubscriptions <> nil then
182
  begin
183
    blockSubscriptions.Delete(ANetState);
184
    ANetState.Subscriptions.Remove(blockSubscriptions);
185
  end;
186
end;
187
188
procedure OnNoOpPacket(ABuffer: TEnhancedMemoryStream; ANetState: TNetState);
189
begin
190
  //no operation
191
end;
192
193
{$WARNINGS OFF}
194
var
195
  i: Integer;
196
197
initialization
198
  for i := 0 to $FF do
199
    PacketHandlers[i] := nil;
200
  PacketHandlers[$01] := TPacketHandler.Create(0, @OnCompressedPacket);
201
  PacketHandlers[$02] := TPacketHandler.Create(0, @OnConnectionHandlerPacket);
202
  PacketHandlers[$03] := TPacketHandler.Create(0, @OnAdminHandlerPacket);
203
  PacketHandlers[$04] := TPacketHandler.Create(0, @OnRequestBlocksPacket);
204
  PacketHandlers[$05] := TPacketHandler.Create(5, @OnFreeBlockPacket);
205
  //$06-$0B handled by landscape
206
  PacketHandlers[$0C] := TPacketHandler.Create(0, @OnClientHandlerPacket);
207
  //$0D handled by radarmap
208
  //$0E handled by landscape
209
  PacketHandlers[$FF] := TPacketHandler.Create(1, @OnNoOpPacket);
210
finalization
211
  for i := 0 to $FF do
212
    if PacketHandlers[i] <> nil then
213
      PacketHandlers[i].Free;
214
{$WARNINGS ON}
215
end.
216