{
a)	const char * get_nodes(void);
返回的字符串是节点名字的列表，用'，'分隔。返回的字符串不用客户程序释放，客户程序也不去修改其内容。
b)	int send_file(const char * name, const char * file);
name是节点的名字，file是文件名。函数通过节点的名字来识别节点，并把文件file传送给指定的节点。
c)	int send_info(const char * name, const char * msg);
name是节点的名字，msg是消息内容。函数通过节点的名字来识别节点，并把msg传送给指定的节点。
d)	typedef void (*on_msg)(const char * name, const char * msg);
void set_msg_handler(on_msg handler);
on_msg是一个call back函数，当接收节点数据时被调用。name是发送节点的名字，msg是发送的消息。
		set_msg_handler函数注册新的消息处理函数
e)	typedef void (*on_file)(const char * name, const char* file);
void set_file_handler(on_file handler);
on_file是一个call back函数，当节点接收完文件时被调用。name是发送节点的名字，file是接收到的文件的本地名字。
		set_file_handler函数注册新的文件处理函数
}
unit PerCastLib;

interface
uses
  sysutils, PKSTconst, PKSTController, classes, idstack;

function init(inifile: string; ServerMode: Boolean): Boolean;
function Open: Boolean;
function Stop: Boolean;
procedure saveini(inifile: string);
procedure uninit;

function get_nodes: string;
function send_file(const node, filename: string): Integer;
procedure set_file_handler(handler: on_fileproc);
function send_info(const node, msg: string): Integer;
procedure set_msg_handler(handler: on_msgproc);
procedure set_rcv_handler(handler: on_rcvproc);
procedure set_send_handler(handler: on_sendproc);


implementation
var
  Controller: TPKSTController;


function init(inifile: string; ServerMode: Boolean): Boolean;
begin
  Result := false;
  if Controller=nil then
    Controller := TPKSTController.Create(ServerMode);
  Controller.Init(inifile);
  Result := true;
end;

function Open: Boolean;
begin
  Result := false;
  if Controller=nil then
    exit;
  Controller.Open;
  Result := true;
end;

function Stop: Boolean;
begin
  Result := false;
  if Controller=nil then
    exit;
  Controller.Stop;
  Result := true;
end;

procedure saveini(inifile: string);
begin
  if Controller=nil then
    exit;
  Controller.Save(inifile);
end;

procedure uninit;
begin
  if Controller<> nil then
  begin
    Controller.Stop;
    FreeAndNil(Controller);
  end;
end;

function get_nodes: string;
var
  sl: TStrings;
  i: Integer;
begin
  Result := '';
  if Controller=nil then exit;
  if not Controller.ServerMode then exit;
  sl := TStringList.Create;
  for i:= Controller.ActiveNodeCount-1 downto 0 do
    sl.add(GUIDToString(Controller.ActiveNode[i].NodeID));
  sl.Delimiter := ',';
  Result := sl.DelimitedText;
  sl.Free;
end;

function send_file(const node, filename: string): Integer;
var
  i: Integer;
  Files: tstrings;
  Nodes: array of TPKSTNode;
begin
  Result := -1;
  setlength(Nodes,1);
  if Controller=nil then exit;
  if not Controller.ServerMode then exit;
  for i:= Controller.ActiveNodeCount-1 downto 0 do
    if GUIDToString(Controller.ActiveNode[i].NodeID) = Node then
    begin
      Files := TStringList.Create;
      Files.Add(filename);
      Nodes[0] := Controller.ActiveNode[i].NodeAdd;
      Controller.Publish(files,Nodes,nil,nil);
      Files.Free;
      Result := 0;
      Exit;
    end;
end;

procedure set_file_handler(handler: on_fileproc);
begin
  if Controller=nil then exit;
  Controller.fileproc := handler;
end;

function send_info(const node, msg: string): Integer;
var
  i: Integer;
  idx: Integer;
  sIP: string;
  PKSTNode: TPKSTNode;
  NodeInfoEX: TPKSTNodeInfoEX;
begin
  Result := -1;
  if Controller=nil then exit;
  if not Controller.ServerMode then
  begin
    idx := Pos(':',Node);
    if idx>0 then
    begin
      try
        PKSTNode.LocalIP.S_addr := 0;
        PKSTNode.Port := StrToInt(Copy(node, idx+1, length(Node)));
        sIP := Copy(node, 1, idx-1);
        PKSTNode.IP := GStack.StringToTInAddr(sIP);
        Controller.SendMsgServer(PKSTNode,msg);
        Result := 0;
        Exit;
      except
      end;
    end
    else
      for i := Controller.ActiveServerCount-1 downto 0 do
      begin
        NodeInfoEX := Controller.ActiveServer[i];
        if GUIDToString(NodeInfoEX.ServerID) = Node then
        begin
          try
            PKSTNode.LocalIP := NodeInfoEX.LocalIP;
            PKSTNode.IP := gstack.StringToTInAddr(gstack.ResolveHost(NodeInfoEX.ServerHost));
            PKSTNode.Port := PKST_SERVERPORT;
            Controller.SendMsgServer(PKSTNode,msg);
            Result := 0;
            Exit;
          except
          end;
        end;
      end;
  end
  else
    for i:= Controller.ActiveNodeCount-1 downto 0 do
      if GUIDToString(Controller.ActiveNode[i].NodeID) = Node then
      begin
        Controller.SendMsg(Controller.ActiveNode[i].NodeAdd,msg);
        Result := 0;
        Exit;
      end;
end;

procedure set_msg_handler(handler: on_msgproc);
begin
  if Controller=nil then exit;
  Controller.msgproc := handler;
end;

procedure set_rcv_handler(handler: on_rcvproc);
begin
  if Controller=nil then exit;
  Controller.rcvproc := handler;
end;

procedure set_send_handler(handler: on_sendproc);
begin
  if Controller=nil then exit;
  Controller.sendproc := handler;
end;

end.
