/// <summary> /// <para>Calls function via this DCOP connection.</para> /// </summary> /// /// <param name="remoteApp"> /// <para>Remote application that will be called.</para> /// </param> /// /// <param name="remoteObject"> /// <para>Remote object in application, whose method will be called.</para> /// </param> /// /// <param name="remoteFunction"> /// <para>Remote function to call. See DcopFunction class for syntax.</para> /// </param> /// /// <param name="parameters"> /// <para>Parameters to pass to function. Keep them in sync with function definition.</para> /// </param> /// /// <value> /// <para>Object, received from remote app. Its type depends on remote app not function name.</para> /// </value> /// /// <exception cref="T:Xsharp.DcopException"> /// <para>Exception raised if there are problems either with connection or naming.</para> /// </exception> public Object Call(String remoteApp, String remoteObject, String remoteFunction, params Object[] parameters) { byte[] header; DcopReply reply; QDataStream ds; DcopFunction fun = new DcopFunction(remoteFunction); MemoryStream mem = new MemoryStream(); try { ds = QDataStream.Marshal(mem, fun, parameters); } catch (Exception) { throw new DcopNamingException("Failed to marshal parameters"); } byte[] data = mem.ToArray(); mem = new MemoryStream(); ds = new QDataStream(mem); ds.Write(appId); ds.Write(remoteApp); ds.Write(remoteObject); ds.Write(fun.Function); ds.Write(data.Length); header = mem.ToArray(); // A *LOT* nicely, isn't? try { BeginMessage((int)DcopMinorOpcode.DcopCall); SendHeader(key, header.Length + data.Length); SendData(header); SendData(data); FinishMessage(); reply = new DcopReply(fun, replyId++); ProcessResponces(reply); // TODO: This is a hack. Do we need message queues? while (reply.status == DcopReply.ReplyStatus.Pending) { ProcessResponces(reply); } } catch (XException xe) { throw new DcopConnectionException("Failed to send message", xe); } if (reply.status == DcopReply.ReplyStatus.Failed) { throw new DcopNamingException("Dcop reply failed, likely that called function does not exists"); } return(reply.replyObject); }
// Process reply message protected override bool ProcessMessage (int opcode, Object oReply) { byte[] data; MemoryStream mem; QDataStream ds; DcopReply reply = oReply as DcopReply; key = ReceiveHeader(4); // Read 4-byte DCOP key data = Receive(); // Read all data mem = new MemoryStream(data); ds = new QDataStream(mem); switch ((DcopMinorOpcode)opcode) { case DcopMinorOpcode.DcopReply: reply.status = DcopReply.ReplyStatus.Ok; reply.transactionId = 0; reply.calledApp = ds.ReadString(); ds.ReadString(); // That's our app. reply.replyType = ds.ReadString(); ds.ReadInt32(); // Reply length, throw it! reply.replyObject = ds.ReadObject(reply.replyType); return(true); case DcopMinorOpcode.DcopReplyFailed: reply.status = DcopReply.ReplyStatus.Failed; reply.transactionId = 0; return(true); // Following are just temporally solution, but for now it's good. case DcopMinorOpcode.DcopReplyWait: reply.status = DcopReply.ReplyStatus.Pending; reply.calledApp = ds.ReadString(); ds.ReadString(); reply.transactionId = ds.ReadInt32(); return(true); case DcopMinorOpcode.DcopReplyDelayed: string ca = ds.ReadString(); ds.ReadString(); int ti = ds.ReadInt32(); if (ca != reply.calledApp || ti != reply.transactionId) { return(false); // Got not that reply what was looking for } reply.status = DcopReply.ReplyStatus.Ok; reply.transactionId = 0; reply.replyType = ds.ReadString(); ds.ReadInt32(); // Reply length, throw it! reply.replyObject = ds.ReadObject(reply.replyType); return(true); default: return(false); // TODO } }
/// <summary> /// <para>Calls function via this DCOP connection.</para> /// </summary> /// /// <param name="remoteApp"> /// <para>Remote application that will be called.</para> /// </param> /// /// <param name="remoteObject"> /// <para>Remote object in application, whose method will be called.</para> /// </param> /// /// <param name="remoteFunction"> /// <para>Remote function to call. See DcopFunction class for syntax.</para> /// </param> /// /// <param name="parameters"> /// <para>Parameters to pass to function. Keep them in sync with function definition.</para> /// </param> /// /// <value> /// <para>Object, received from remote app. Its type depends on remote app not function name.</para> /// </value> /// /// <exception cref="T:Xsharp.DcopException"> /// <para>Exception raised if there are problems either with connection or naming.</para> /// </exception> public Object Call(String remoteApp, String remoteObject, String remoteFunction, params Object[] parameters) { byte[] header; DcopReply reply; QDataStream ds; DcopFunction fun = new DcopFunction(remoteFunction); MemoryStream mem = new MemoryStream(); try { ds = QDataStream.Marshal(mem, fun, parameters); } catch (Exception) { throw new DcopNamingException("Failed to marshal parameters"); } byte[] data = mem.ToArray(); mem = new MemoryStream(); ds = new QDataStream(mem); ds.Write(appId); ds.Write(remoteApp); ds.Write(remoteObject); ds.Write(fun.Function); ds.Write(data.Length); header = mem.ToArray(); // A *LOT* nicely, isn't? try { BeginMessage((int)DcopMinorOpcode.DcopCall); SendHeader(key, header.Length + data.Length); SendData(header); SendData(data); FinishMessage(); reply = new DcopReply(fun, replyId++); ProcessResponces(reply); // TODO: This is a hack. Do we need message queues? while(reply.status == DcopReply.ReplyStatus.Pending) { ProcessResponces(reply); } } catch (XException xe) { throw new DcopConnectionException("Failed to send message", xe); } if(reply.status == DcopReply.ReplyStatus.Failed) { throw new DcopNamingException("Dcop reply failed, likely that called function does not exists"); } return reply.replyObject; }