internal virtual void sendProfile(string uri, string datum, ChannelImpl ch) { // Send the profile System.Text.StringBuilder sb = new System.Text.StringBuilder(); sb.Append("<profile uri='"); sb.Append(uri); if ((object) datum != null) { sb.Append("'><![CDATA["); sb.Append(datum); sb.Append("]]></profile>"); } else { sb.Append("' />"); } OutputDataStream ds = new ByteOutputDataStream(MimeHeaders.BEEP_XML_CONTENT_TYPE, System.Text.Encoding.ASCII.GetBytes(sb.ToString())); // Store the Channel channels[ch.NumberAsString] = ch; ((IMessageMSG) zero.AppData).sendRPY(ds); }
/// <summary>The Initiator Oriented close channel call...but this one is not an /// external call, it's invoked from Channel.close();</summary> /// <param name="channel"></param> /// <param name="code"></param> /// <param name="xmlLang"></param> /// <exception cref="BEEPException" /> internal virtual void closeChannel(ChannelImpl channel, BEEPStatusCode code, string xmlLang) { // Construct Message System.Text.StringBuilder closeBuffer = new System.Text.StringBuilder(); closeBuffer.Append("<close number='"); closeBuffer.Append(channel.NumberAsString); closeBuffer.Append("' code='"); closeBuffer.Append(code); if ((object) xmlLang != null) { closeBuffer.Append("' xml:lang='"); closeBuffer.Append(xmlLang); } closeBuffer.Append("' />"); // Lock necessary because we have to know the msgNo // before we send the message, in order to be able // to associate the reply with this start request CloseReplyListener reply = new CloseReplyListener(this, channel); lock (reply) { OutputDataStream ds = new ByteOutputDataStream(MimeHeaders.BEEP_XML_CONTENT_TYPE, System.Text.Encoding.ASCII.GetBytes(closeBuffer.ToString())); this.zero.sendMSG(ds, reply); try { System.Threading.Monitor.Wait(reply); } catch (System.Threading.ThreadInterruptedException e) { log.error("Error waiting for reply", e); throw new BEEPException("Interrupted waiting for reply"); } } // check the channel state and return the appropriate exception if (reply.isError()) { throw reply.getError(); } if (channel.getState() != core.ChannelState.STATE_CLOSED) { throw new BEEPException("Error channel state (" + channel.getState() + ")"); } fireChannelClosed(channel); }
internal virtual IChannel startChannelRequest(System.Collections.ICollection profiles, IRequestHandler handler, bool tuning) { string channelNumber = NextFreeChannelNumber; // create the message in a buffer and send it System.Text.StringBuilder startBuffer = new System.Text.StringBuilder(); startBuffer.Append("<start number='"); startBuffer.Append(channelNumber); if ((object) serverName != null && !sentServerName) { startBuffer.Append("' serverName='"); startBuffer.Append(serverName); } startBuffer.Append("'>"); foreach(StartChannelProfile p in profiles) { // @todo maybe we should check these against peerSupportedProfiles startBuffer.Append("<profile uri='"); startBuffer.Append(p.uri); startBuffer.Append("' "); if ((object) p.data == null) { startBuffer.Append(" />"); } else { if (p.base64Encoding) { startBuffer.Append("encoding='base64' "); } startBuffer.Append("><![CDATA["); startBuffer.Append(p.data); startBuffer.Append("]]></profile>"); } } startBuffer.Append("</start>"); // @todo handle the data element // Create a channel ChannelImpl ch = new ChannelImpl(null, channelNumber, handler, false, this); // Make a message OutputDataStream ds = new ByteOutputDataStream(MimeHeaders.BEEP_XML_CONTENT_TYPE, System.Text.Encoding.ASCII.GetBytes(startBuffer.ToString())); if (tuning) { this.changeState(core.SessionState.SESSION_STATE_TUNING_PENDING); this.changeState(core.SessionState.SESSION_STATE_TUNING); this.zero.setState(core.ChannelState.STATE_TUNING); } // Tell Channel Zero to start us up StartReplyListener reply = new StartReplyListener(this, ch); lock (reply) { this.zero.sendMSG(ds, reply); try { System.Threading.Monitor.Wait(reply); } catch (System.Threading.ThreadInterruptedException e) { log.error("Interrupted waiting for reply", e); throw new BEEPException("Interrupted waiting for reply"); } } // check the channel state and return the appropriate exception if (reply.isError()) { throw reply.getError(); } if (ch.getState() != core.ChannelState.STATE_ACTIVE) { throw new BEEPException("Error channel state (" + ch.getState() + ")"); } if (tuning) { ch.setState(core.ChannelState.STATE_TUNING); } if ((object) serverName != null) { sentServerName = true; } fireChannelStarted(ch); return ch; }
private void sendGreeting() { log.debug("sendGreeting"); // get the greeting from the session byte[] greeting = this.ProfileRegistry.getGreeting(this); ByteOutputDataStream f = new ByteOutputDataStream(MimeHeaders.BEEP_XML_CONTENT_TYPE, greeting); IMessageMSG m = new MessageMSGImpl(this.zero, 0, null); // send the greeting m.sendRPY(f); }
private void receiveCloseChannelZero() { // closing the session // @todo fireEvent(SESSION_STATE_CLOSING); if (log.isDebugEnabled()) { log.debug("Closing Session with " + channels.Count + " channels"); } try { changeState(core.SessionState.SESSION_STATE_CLOSE_PENDING); changeState(core.SessionState.SESSION_STATE_CLOSING); } catch (BEEPException) { terminate("Error changing Session state to closing."); return ; } object[] keys = new object[channels.Keys.Count]; channels.Keys.CopyTo(keys,0); foreach(object key in keys) { ChannelImpl ch = (ChannelImpl) channels[key]; // if this channel is not zero, call the channel's scl if (ch.Number == 0) { continue; } IStartChannelListener scl = profileRegistry.getStartChannelListener(this.tuningProperties, ch.getProfile()); // check locally first to see if it is ok to close the channel try { scl.CloseChannel(ch); channels.Remove(key); } catch (CloseChannelException e) { try { changeState(core.SessionState.SESSION_STATE_ACTIVE); enableIO(); throw e; } catch (BEEPException) { terminate("Error changing Session state from closing " + "to active"); return ; } } fireChannelClosed(ch); } OutputDataStream sds = new ByteOutputDataStream(MimeHeaders.BEEP_XML_CONTENT_TYPE, OK_ELEMENT); try { ((IMessageMSG) zero.AppData).sendRPY(sds); } catch (BEEPException) { terminate("Error sending RPY for <close> for channel 0"); return ; } try { this.changeState(core.SessionState.SESSION_STATE_CLOSED); } catch (BEEPException e) { log.error("Error changing state", e); } fireSessionClosed(); }
/// <summary>This method is called when Channel Zero receives - from our /// session peer - a request to close a channel.</summary> /// <param name="channelNumber"></param> /// <param name="code"></param> /// <param name="xmlLang"></param> /// <param name="data"></param> /// <exception cref="BEEPException" /> private void receiveCloseChannel(string channelNumber, string code, string xmlLang, string data) { // @todo fix close channel if (channelNumber.Equals(CHANNEL_ZERO)) { receiveCloseChannelZero(); return ; } enableIO(); ChannelImpl channel = (ChannelImpl) channels[channelNumber]; if (channel == null) { throw new BEEPError(BEEPStatusCode.PARAMETER_INVALID, "Close requested for nonexistent channel"); } try { IStartChannelListener scl = profileRegistry.getStartChannelListener(this.tuningProperties, channel.getProfile()); scl.CloseChannel(channel); channel.setState(core.ChannelState.STATE_CLOSING); } catch (BEEPError x) { channel.setState(core.ChannelState.STATE_CLOSING); throw x; } // Send an ok OutputDataStream sds = new ByteOutputDataStream(MimeHeaders.BEEP_XML_CONTENT_TYPE, OK_ELEMENT); try { ((IMessageMSG) zero.AppData).sendRPY(sds); } catch (BEEPException) { terminate("Error sending RPY for <close>"); return ; } // We need to close the server socket at some point ! this.disableIO(); // We're past the CCL approval channel.setState(core.ChannelState.STATE_CLOSED); channels.Remove(channel.NumberAsString); fireChannelClosed(channel); }