2 (* Communication between applications and running brodnet daemon. *)
24 procedure SetSelectFDS(var FDS
: BaseUnix
.tFDSet
);
25 procedure HandleConnect(const ls
:tListeningSocket
);
26 procedure Receive(const FDS
: BaseUnix
.tFDSet
);
28 {hooks for hooks in daemon}
29 procedure NotifyPeerStateChange( event
: byte; info
:Peers
.tInfo
);
30 procedure NotifyTransfer( id
:tFID
; done
,total
:longword
; by
: tBys
);
31 procedure NotifyQuit( unexcepted
:boolean );
32 procedure NotifyNeighbState( pid
:tPID
; addr
:netaddr
.t
; hop
:word );
35 var OnTerminateRequest
:procedure;
36 const cTransferBy
:Transfer
.tBy
=24;
38 type eFull
=class(Exception
) end;
41 - Aby sa upratal trochu loop v daemone:
42 - poskytne proceduru co modifikuje select-set
43 - ohandluje si callback z daemona z vysledkyu zo selectu
44 - Chceme abstrahovať socket, aby sa to dalo spustit aj bez daemona?
45 - naco, aj tak to bez neho nejde
46 - manažuje si pripojenych sam
47 - handluje peerstatechange, terminate, a vsetko
53 type tDCFlag
=(cfPeerStates
,cfPeerStates0
);
55 type tDaemonController
=class (tObject
)
63 constructor Create(asocket
:tStream
; from
:NetAddr
.t
);
64 destructor Destroy
; override;
65 procedure NotifyPeerStateChange( event
: byte; info
:Peers
.tInfo
);
67 procedure NotifyQuit( unexcepted
:boolean );
69 procedure NotifyTransfer( aid
:tFID
; done
,total
:longword
; by
: tBys
);
70 procedure CmdRequestTransfer
;
71 procedure CmdQueryTransfer(op
:byte);
72 procedure NotifyNeighb( pid
:Neighb
.tPID
; addr
: netaddr
.t
; hopcount
: word );
73 procedure CmdGetNeighb
;
74 procedure CmdGetNeighbPID
;
77 var Clients
: array [1..8] of tDaemonController
;
79 procedure tDaemonController
.Run
;
83 log
.debug('CMD/#'+IntToStr(id
)+' Command: #'+IntToStr(cmd
));
86 ccPeerStates
: flags
:=flags
><[cfPeerStates
];
87 //ccPeerStatesOff: flags:= flags -[cfPeerStates,ccPeerStates];
88 ccTerminate
: if assigned(OnTerminateRequest
) then OnTerminateRequest
;
89 ccQuit
: Finished
:=true;
91 ccTransferRequest
:CmdRequestTransfer
;
92 ccTransferProgress
:CmdQueryTransfer(0);
93 ccTransferAbort
:CmdQueryTransfer(1);
94 ccGetNeighb
:CmdGetNeighb
;
95 ccGetNeighbPID
:CmdGetNeighbPID
;
96 //ccGetNeighbAddr:CmdGetNeighbAddr;
99 except on e
:EReadError
do begin
100 log
.debug('Command errored '+e
.classname
);
107 procedure tDaemonController
.NotifyPeerStateChange( event
: byte; info
:Peers
.tInfo
);
110 if not (cfPeerStates
in flags
) then exit
;
111 if (event
=0) and ( not (cfPeerStates0
in flags
)) then exit
;
112 io
.WriteByte(cePeerState
);
114 io
.WriteBuffer(info
.addr
,sizeof(info
.addr
));
115 w
:=trunc(info
.delta
*MSecsPerDay
);
118 procedure tDaemonController
.CmdAddPeer
;
121 io
.ReadBuffer(addr
,sizeof(addr
));
122 if addr
.IsNil
then log
.error('Addr is nil') else Peers
.Add(addr
);
126 procedure tDaemonController
.CmdInvalid
;
128 io
.WriteByte(ceInvalid
);
130 log
.error('Invalid command');
132 procedure tDaemonController
.NotifyQuit( unexcepted
:boolean );
135 io
.WriteByte(ceQuit
);
136 if unexcepted
then exp
:=1 else exp
:=0;
141 procedure tDaemonController
.NotifyTransfer( aid
:tFID
; done
,total
:longword
; by
: tBys
);
144 if not (cTransferBy
in by
) then exit
;
145 io
.WriteByte(ceTransfer
);
146 io
.WriteBuffer(aid
,sizeof(aid
));
147 w
:=done
; io
.WriteBuffer(w
,4);
148 w
:=total
; io
.WriteBuffer(w
,4);
149 (*io.WriteByte(by);*)
151 procedure tDaemonController
.CmdRequestTransfer
;
155 io
.ReadBuffer(a
,sizeof(a
));
156 io
.ReadBuffer(addr
,sizeof(addr
));
157 Transfer
.RequestFile( addr
, a
, cTransferBy
);
159 procedure tDaemonController
.CmdQueryTransfer(op
:byte);
160 var done
,total
:longword
;
161 var fid
:Transfer
.tFID
;
163 io
.ReadBuffer(fid
,sizeof(fid
));
166 Transfer
.Query(fid
,done
,total
);
167 NotifyTransfer(fid
,done
,total
,[cTransferBy
]);
169 1: Transfer
.RecvFileAbort(fid
);
173 procedure tDaemonController
.NotifyNeighb( pid
:Neighb
.tPID
; addr
: netaddr
.t
; hopcount
: word );
176 if not (cfPeerStates
in flags
) then exit
;
180 io
.WriteByte(ceNeighbState
);
181 io
.WriteBuffer(n
,sizeof(n
));
183 procedure NotifyNeighbState( pid
:tPID
; addr
:netaddr
.t
; hop
:word );
186 for i
:=1 to high(Clients
) do if assigned(Clients
[i
]) then Clients
[i
].NotifyNeighb(pid
,addr
,hop
);
189 procedure tDaemonController
.CmdGetNeighb
;
194 while i
.Next
do begin
198 io
.WriteByte(ceNeighbs
);
199 io
.WriteBuffer(n
,sizeof(n
));
201 io
.WriteByte(ceNeighbsEnd
);
204 procedure tDaemonController
.CmdGetNeighbPID
;
210 io
.ReadBuffer(pid
,sizeof(pid
));
212 Neighb
.GetRoute(pid
,n
.addr
,wo
,i
);
214 while assigned(i
) do begin
215 io
.WriteByte(ceNeighbs
);
216 io
.WriteBuffer(n
,sizeof(n
));
217 Neighb
.GetRoute(pid
,n
.addr
,wo
,i
);
220 io
.WriteByte(ceNeighbsEnd
);
223 constructor tDaemonController
.Create(asocket
:tStream
; from
:NetAddr
.t
);
230 destructor tDaemonController
.Destroy
;
234 procedure SetSelectFDS(var FDS
: BaseUnix
.tFDSet
);
237 for i
:=1 to high(Clients
) do if assigned(Clients
[i
]) then BaseUnix
.fpfd_set((Clients
[i
].io
as tSocketStream
).Handle
,FDS
);
240 procedure HandleConnect(const ls
:tListeningSocket
);
241 var stream
:tSocketStream
;
244 var consocket
:tSocket
;
246 ci
:=1; while true do begin
247 if ci
>high(Clients
) then break
;
248 if not assigned(Clients
[ci
]) then break
;
251 ls
.Accept(consocket
,addr
);
252 stream
:=tSocketStream
.Create(consocket
);
253 if ci
>high(Clients
) then begin
254 log
.error('Too many clients on command port'); //raise eFull.Create('Too many clients on command port');
257 log
.info('CMD/#'+IntToStr(ci
)+' connect from '+String(addr
));
258 Clients
[ci
]:=tDaemonController
.Create(stream
,addr
);
263 procedure Receive(const FDS
: BaseUnix
.tFDSet
);
266 for i
:=1 to high(Clients
) do if assigned(Clients
[i
]) and (BaseUnix
.fpfd_isset((Clients
[i
].io
as tSocketStream
).Handle
,FDS
)=1) then begin
268 if Clients
[i
].Finished
then begin
269 log
.info('CMD/#'+IntToStr(i
)+ ' disconnect');
271 freeandnil(Clients
[i
]);
276 procedure NotifyPeerStateChange( event
: byte; info
:Peers
.tInfo
);
279 for i
:=1 to high(Clients
) do if assigned(Clients
[i
]) then Clients
[i
].NotifyPeerStateChange(event
,info
);
282 procedure NotifyQuit( unexcepted
:boolean );
285 for i
:=1 to high(Clients
) do if assigned(Clients
[i
]) then begin
286 Clients
[i
].NotifyQuit(unexcepted
);
288 freeandnil(Clients
[i
]);
292 procedure NotifyTransfer( id
:tFID
; done
,total
:longword
; by
: tBys
);
295 for i
:=1 to high(Clients
) do if assigned(Clients
[i
]) then Clients
[i
].NotifyTransfer(id
,done
,total
,by
);
301 for i
:=1 to high(Clients
) do Clients
[i
]:=nil;