private void cleanup() { stopTimer(); // Make sure timer stopped try { acceptReplies = false; conn?.removeMessage(this); // Empty out any accumuluated replies if (replies != null) { while (replies.Count != 0) { var temp_object = replies[0]; replies.RemoveAt(0); object generatedAux = temp_object; } } } catch (Exception ex) { // nothing } // Let GC clean up this stuff, leave name in case finalized is called conn = null; msg = null; // agent = null; // leave this reference queue = null; //replies = null; //leave this since we use it as a semaphore bindprops = null; }
private void cleanup() { stopTimer(); // Make sure timer stopped try { acceptReplies = false; if (conn != null) { conn.removeMessage(this); } // Empty out any accumuluated replies if (replies != null) { while (!(replies.Count == 0)) { object temp_object; temp_object = replies[0]; replies.RemoveAt(0); var generatedAux = temp_object; } } } catch (Exception ex) { LogManager.GetCurrentClassLogger().Warn("Exception swallowed", ex); } _stackTraceCleanup = Environment.StackTrace; // Let GC clean up this stuff, leave name in case finalized is called conn = null; msg = null; // agent = null; // leave this reference queue = null; //replies = null; //leave this since we use it as a semaphore bindprops = null; }
/// <summary> Send a request to the server. A Message class is created /// for the specified request which causes the message to be sent. /// The request is added to the list of messages being managed by /// this agent. /// /// </summary> /// <param name="conn">the connection that identifies the server. /// /// </param> /// <param name="msg">the LdapMessage to send /// /// </param> /// <param name="timeOut">the interval to wait for the message to complete or /// <code>null</code> if infinite. /// </param> /// <param name="queue">the LdapMessageQueue associated with this request. /// </param> /* package */ internal void sendMessage(Connection conn, LdapMessage msg, int timeOut, LdapMessageQueue queue, BindProperties bindProps) { // creating a messageInfo causes the message to be sent // and a timer to be started if needed. Message message = new Message(msg, timeOut, conn, this, queue, bindProps); messages.Add(message); message.sendMessage(); // Now send message to server }
/// <summary> /// Send a request to the server. A Message class is created /// for the specified request which causes the message to be sent. /// The request is added to the list of messages being managed by /// this agent. /// </summary> /// <param name="conn"> /// the connection that identifies the server. /// </param> /// <param name="msg"> /// the LdapMessage to send. /// </param> /// <param name="timeOut"> /// the interval to wait for the message to complete or. /// <code>null</code> if infinite. /// </param> internal void SendMessage(Connection conn, LdapMessage msg, int timeOut, BindProperties bindProps) { Debug.WriteLine(msg.ToString()); // creating a messageInfo causes the message to be sent // and a timer to be started if needed. var message = new Message(msg, timeOut, conn, this, bindProps); _messages.Add(message); message.SendMessage(); // Now send message to server }
private BindProperties bindprops; // Bind properties if a bind request internal Message(LdapMessage msg, int mslimit, Connection conn, MessageAgent agent, LdapMessageQueue queue, BindProperties bindprops) { InitBlock(); this.msg = msg; this.conn = conn; this.agent = agent; this.queue = queue; this.mslimit = mslimit; msgId = msg.MessageID; this.bindprops = bindprops; }
/// <summary> /// Send a request to the server. A Message class is created /// for the specified request which causes the message to be sent. /// The request is added to the list of messages being managed by /// this agent. /// </summary> /// <param name="conn"> /// the connection that identifies the server. /// </param> /// <param name="msg"> /// the LdapMessage to send. /// </param> /// <param name="timeOut"> /// the interval to wait for the message to complete or. /// <code>null</code> if infinite. /// </param> internal Task SendMessageAsync(Connection conn, LdapMessage msg, int timeOut, BindProperties bindProps, CancellationToken cancellationToken) { Debug.WriteLine(msg.ToString()); // creating a messageInfo causes the message to be sent // and a timer to be started if needed. var message = new Message(msg, timeOut, conn, this, bindProps); _messages.Add(message); return(message.SendMessageAsync(cancellationToken)); // Now send message to server }
private bool waitForReply_Renamed_Field = true; // true if wait for reply #endregion Fields #region Constructors internal Message(LdapMessage msg, int mslimit, Connection conn, MessageAgent agent, LdapMessageQueue queue, BindProperties bindprops) { InitBlock(); this.msg = msg; this.conn = conn; this.agent = agent; this.queue = queue; this.mslimit = mslimit; this.msgId = msg.MessageID; this.bindprops = bindprops; return ; }
private bool _waitForReplyRenamedField = true; // true if wait for reply internal Message(LdapMessage msg, int mslimit, Connection conn, MessageAgent agent, BindProperties bindprops) { _conn = conn ?? throw new ArgumentNullException(nameof(conn)); _stackTraceCreation = Environment.StackTrace; _replies = new MessageVector(5); Request = msg; MessageAgent = agent; _mslimit = mslimit; MessageId = msg.MessageId; _bindprops = bindprops; }
private BindProperties bindprops; // Bind properties if a bind request internal Message(LdapMessage msg, int mslimit, Connection conn, MessageAgent agent, LdapMessageQueue queue, BindProperties bindprops) { if (conn == null) { throw new ArgumentNullException(nameof(conn)); } _stackTraceCreation = Environment.StackTrace; InitBlock(); this.msg = msg; this.conn = conn; this.agent = agent; this.queue = queue; this.mslimit = mslimit; msgId = msg.MessageID; this.bindprops = bindprops; }
/// <summary> Sends an Ldap request to a directory server. /// /// The specified the Ldap request is sent to the directory server /// associated with this connection using default constraints. An Ldap /// request object is a subclass {@link LdapMessage} with the operation /// type set to one of the request types. You can build a request by using /// the request classes found in this package /// /// You should note that, since Ldap requests sent to the server /// using sendRequest are asynchronous, automatic referral following /// does not apply to these requests. /// /// </summary> /// <param name="request">The Ldap request to send to the directory server. /// </param> /// <param name="queue"> The queue for messages returned from a server in /// response to this request. If it is null, a /// queue object is created internally. /// </param> /// <exception> LdapException A general exception which includes an error /// message and an Ldap error code. /// /// </exception> /// <seealso cref="LdapMessage.Type"> /// </seealso> /// <seealso cref="RfcLdapMessage.isRequest"> /// </seealso> public virtual LdapMessageQueue SendRequest(LdapMessage request, LdapMessageQueue queue) { return SendRequest(request, queue, null); }
private void cleanup() { stopTimer(); // Make sure timer stopped try { acceptReplies = false; if (conn != null) { conn.removeMessage(this); } // Empty out any accumuluated replies if (replies != null) { while (!(replies.Count == 0)) { System.Object temp_object; temp_object = replies[0]; replies.RemoveAt(0); System.Object generatedAux = temp_object; } } } catch (System.Exception ex) { // nothing } // Let GC clean up this stuff, leave name in case finalized is called conn = null; msg = null; // agent = null; // leave this reference queue = null; //replies = null; //leave this since we use it as a semaphore bindprops = null; return ; }
/// <summary> Gets the next reply from the reply queue or waits until one is there /// /// </summary> /// <returns> the next reply message on the reply queue or null /// </returns> /* package */ internal virtual System.Object waitForReply() { if (replies == null) { return null; } // sync on message so don't confuse with timer thread lock (replies) { System.Object msg = null; while (waitForReply_Renamed_Field) { if ((replies.Count == 0)) { try { System.Threading.Monitor.Wait(replies); } catch (System.Threading.ThreadInterruptedException ir) { ; // do nothing } if (waitForReply_Renamed_Field) { continue; } else { break; } } else { System.Object temp_object; temp_object = replies[0]; replies.RemoveAt(0); msg = temp_object; // Atomic get and remove } if ((complete || !acceptReplies) && (replies.Count == 0)) { // Remove msg from connection queue when last reply read conn.removeMessage(this); } else { } return msg; } return null; } }
protected void NotifyListeners(LdapMessage sourceMessage, EventClassifiers aClassification, int nType) { // first let the actual source Notify the listeners with // appropriate EventArgs bool bListenersNotified = NotifyEventListeners(sourceMessage, aClassification, nType); if (!bListenersNotified) { // Actual EventSource could not recognize the event // Just notify the listeners for generic directory events NotifyDirectoryListeners(sourceMessage, aClassification); } }
protected void NotifyDirectoryListeners(LdapMessage sourceMessage, EventClassifiers aClassification) { NotifyDirectoryListeners(new DirectoryEventArgs(sourceMessage, aClassification)); }
protected void NotifyExceptionListeners(LdapMessage sourceMessage, LdapException ldapException) { if (null != directory_exception_event) { directory_exception_event(this, new DirectoryExceptionEventArgs(sourceMessage, ldapException)); } }
/// <summary> Builds a new request replacing dn, scope, and filter where approprate /// /// </summary> /// <param name="msg">the original LdapMessage to build the new request from /// /// </param> /// <param name="url">the referral url /// /// </param> /// <returns> a new LdapMessage with appropriate information replaced /// /// </returns> /// <exception> LdapException A general exception which includes an error /// message and an Ldap error code. /// </exception> private LdapMessage rebuildRequest(LdapMessage msg, LdapUrl url, bool reference) { System.String dn = url.getDN(); // new base System.String filter = null; switch (msg.Type) { case LdapMessage.SEARCH_REQUEST: if (reference) { filter = url.Filter; } break; // We are allowed to get a referral for the following case LdapMessage.ADD_REQUEST: case LdapMessage.BIND_REQUEST: case LdapMessage.COMPARE_REQUEST: case LdapMessage.DEL_REQUEST: case LdapMessage.EXTENDED_REQUEST: case LdapMessage.MODIFY_RDN_REQUEST: case LdapMessage.MODIFY_REQUEST: break; // The following return no response case LdapMessage.ABANDON_REQUEST: case LdapMessage.UNBIND_REQUEST: default: throw new LdapLocalException(ExceptionMessages.IMPROPER_REFERRAL, new System.Object[]{msg.Type}, LdapException.LOCAL_ERROR); } return msg.Clone(dn, filter, reference); }
/// <summary> Follow referrals if necessary referral following enabled. /// This function is called only by synchronous requests. /// Search responses come here only if referral following is /// enabled and if we are processing a SearchResultReference /// or a Response with a status of REFERRAL, i.e. we are /// going to follow a referral. /// /// This functions recursively follows a referral until a result /// is returned or until the hop limit is reached. /// /// </summary> /// <param name="queue">The LdapResponseQueue for this request /// /// </param> /// <param name="cons">The constraints that apply to the request /// /// </param> /// <param name="msg">The referral or search reference response message /// /// </param> /// <param name="initialReferrals">The referral array returned from the /// initial request. /// /// </param> /// <param name="hopCount">the number of hops already used while /// following this referral /// /// </param> /// <param name="searchReference">true if the message is a search reference /// /// </param> /// <param name="connectionList">An optional array list used to store /// the LdapConnection objects used in following the referral. /// /// </param> /// <returns> The array list used to store the all LdapConnection objects /// used in following the referral. The list will be empty /// if there were none. /// /// </returns> /// <exception> LdapException A general exception which includes an error /// message and an Ldap error code. /// </exception> /* package */ internal virtual System.Collections.ArrayList chaseReferral(LdapMessageQueue queue, LdapConstraints cons, LdapMessage msg, System.String[] initialReferrals, int hopCount, bool searchReference, System.Collections.ArrayList connectionList) { System.Collections.ArrayList connList = connectionList; LdapConnection rconn = null; // new conn for following referral ReferralInfo rinfo = null; // referral info LdapMessage origMsg; // Get a place to store new connections if (connList == null) { connList = new System.Collections.ArrayList(cons.HopLimit); } // Following referrals or search reference System.String[] refs; // referral list if (initialReferrals != null) { // Search continuation reference from a search request refs = initialReferrals; origMsg = msg.RequestingMessage; } else { // Not a search request LdapResponse resp = (LdapResponse) queue.getResponse(); if (resp.ResultCode != LdapException.REFERRAL) { // Not referral result,throw Exception if nonzero result resp.chkResultCode(); return connList; } // We have a referral response refs = resp.Referrals; origMsg = resp.RequestingMessage; } LdapUrl refUrl; // referral represented as URL try { // increment hop count, check max hops if (hopCount++ > cons.HopLimit) { throw new LdapLocalException("Max hops exceeded", LdapException.REFERRAL_LIMIT_EXCEEDED); } // Get a connection to follow the referral rinfo = getReferralConnection(refs); rconn = rinfo.ReferralConnection; refUrl = rinfo.ReferralUrl; connList.Add(rconn); // rebuild msg into new msg changing msgID,dn,scope,filter LdapMessage newMsg = rebuildRequest(origMsg, refUrl, searchReference); // Send new message on new connection try { MessageAgent agent; if (queue is LdapResponseQueue) { agent = queue.MessageAgent; } else { agent = queue.MessageAgent; } agent.sendMessage(rconn.Connection, newMsg, defSearchCons.TimeLimit, queue, null); } catch (InterThreadException ex) { // Error ending request to referred server LdapReferralException rex = new LdapReferralException(ExceptionMessages.REFERRAL_SEND, LdapException.CONNECT_ERROR, null, ex); rex.setReferrals(initialReferrals); ReferralInfo ref_Renamed = rconn.Connection.ActiveReferral; rex.FailedReferral = ref_Renamed.ReferralUrl.ToString(); throw rex; } if (initialReferrals == null) { // For operation results, when all responses are complete, // the stack unwinds back to the original and returns // to the application. // An exception is thrown for an error connList = chaseReferral(queue, cons, null, null, hopCount, false, connList); } else { // For search, just return to LdapSearchResults object return connList; } } catch (System.Exception ex) { if (ex is LdapReferralException) { throw (LdapReferralException) ex; } else { // Set referral list and failed referral LdapReferralException rex = new LdapReferralException(ExceptionMessages.REFERRAL_ERROR, ex); rex.setReferrals(refs); if (rinfo != null) { rex.FailedReferral = rinfo.ReferralUrl.ToString(); } else { rex.FailedReferral = refs[refs.Length - 1]; } throw rex; } } return connList; }
//************************************************************************* // helper methods //************************************************************************* /// <summary> Locates the appropriate message agent and sends /// the Ldap request to a directory server. /// /// </summary> /// <param name="msg">the message to send /// /// </param> /// <param name="timeout">the timeout value /// /// </param> /// <param name="queue">the response queue or null /// /// </param> /// <returns> the LdapResponseQueue for this request /// /// </returns> /// <exception> LdapException A general exception which includes an error /// message and an Ldap error code. /// </exception> private LdapResponseQueue SendRequestToServer(LdapMessage msg, int timeout, LdapResponseQueue queue, BindProperties bindProps) { MessageAgent agent; if (queue == null) { agent = new MessageAgent(); queue = new LdapResponseQueue(agent); } else { agent = queue.MessageAgent; } agent.sendMessage(conn, msg, timeout, queue, bindProps); return queue; }
NotifyEventListeners(LdapMessage sourceMessage, EventClassifiers aClassification, int nType);
/// <summary> Writes an LdapMessage to the Ldap server over a socket. /// /// </summary> /// <param name="msg">the message to write. /// </param> /* package */ internal void writeMessage(LdapMessage msg) { int id; // Get the correct semaphore id for bind operations if (bindSemaphoreId == 0) { // Semaphore id for normal operations id = msg.MessageID; } else { // Semaphore id for sasl bind operations id = bindSemaphoreId; } System.IO.Stream myOut = out_Renamed; acquireWriteSemaphore(id); try { if (myOut == null) { throw new System.IO.IOException("Output stream not initialized"); } sbyte[] ber = msg.Asn1Object.getEncoding(encoder); myOut.Write(SupportClass.ToByteArray(ber), 0, ber.Length); myOut.Flush(); } catch (System.IO.IOException ioe) { /* * IOException could be due to a server shutdown notification which * caused our Connection to quit. If so we send back a slightly * different error message. We could have checked this a little * earlier in the method but that would be an expensive check each * time we send out a message. Since this shutdown request is * going to be an infrequent occurence we check for it only when * we get an IOException. shutdown() will do the cleanup. */ if (clientActive) { // We beliefe the connection was alive if (unsolSvrShutDnNotification) { // got server shutdown throw new LdapException(ExceptionMessages.SERVER_SHUTDOWN_REQ, new System.Object[]{host, port}, LdapException.CONNECT_ERROR, null, ioe); } // Other I/O Exceptions on host:port are reported as is throw new LdapException(ExceptionMessages.IO_EXCEPTION, new System.Object[]{host, port}, LdapException.CONNECT_ERROR, null, ioe); } } finally { freeWriteSemaphore(id); } return ; }
/// <summary> Send a request to the server. A Message class is created /// for the specified request which causes the message to be sent. /// The request is added to the list of messages being managed by /// this agent. /// /// </summary> /// <param name="conn">the connection that identifies the server. /// /// </param> /// <param name="msg">the LdapMessage to send /// /// </param> /// <param name="timeOut">the interval to wait for the message to complete or /// <code>null</code> if infinite. /// </param> /// <param name="queue">the LdapMessageQueue associated with this request. /// </param> /* package */ internal void sendMessage(Connection conn, LdapMessage msg, int timeOut, LdapMessageQueue queue, BindProperties bindProps) { // creating a messageInfo causes the message to be sent // and a timer to be started if needed. Message message = new Message(msg, timeOut, conn, this, queue, bindProps); messages.Add(message); message.sendMessage(); // Now send message to server return ; }
} // end of method run protected void processmessage(LdapMessage response) { if (response is LdapResponse) { try { ((LdapResponse) response).chkResultCode(); m_objLdapEventSource.NotifyEventListeners(response, EventClassifiers.CLASSIFICATION_UNKNOWN, EVENT_TYPE_UNKNOWN); } catch (LdapException e) { m_objLdapEventSource.NotifyExceptionListeners(response, e); } } else { m_objLdapEventSource.NotifyEventListeners(response, EventClassifiers.CLASSIFICATION_UNKNOWN, EVENT_TYPE_UNKNOWN); } } // end of method processmessage
/// <summary> Writes an LdapMessage to the Ldap server over a socket. /// /// </summary> /// <param name="msg">the message to write. /// </param> /* package */ internal void writeMessage(LdapMessage msg) { int id; // Get the correct semaphore id for bind operations if (bindSemaphoreId == 0) { // Semaphore id for normal operations id = msg.MessageID; } else { // Semaphore id for sasl bind operations id = bindSemaphoreId; } System.IO.Stream myOut = out_Renamed; acquireWriteSemaphore(id); try { if (myOut == null) { throw new System.IO.IOException("Output stream not initialized"); } if (!(myOut.CanWrite)) { return; } sbyte[] ber = msg.Asn1Object.getEncoding(encoder); myOut.Write(SupportClass.ToByteArray(ber), 0, ber.Length); myOut.Flush(); } catch (System.IO.IOException ioe) { if ((msg.Type == LdapMessage.BIND_REQUEST) && (ssl)) { string strMsg = "Following problem(s) occurred while establishing SSL based Connection : "; if (handshakeProblemsEncountered.Count > 0) { strMsg += GetProblemMessage((CertificateProblem)handshakeProblemsEncountered[0]); for (int nProbIndex = 1; nProbIndex < handshakeProblemsEncountered.Count; nProbIndex++) { strMsg += ", " + GetProblemMessage((CertificateProblem)handshakeProblemsEncountered[nProbIndex]); } } else { strMsg += "Unknown Certificate Problem"; } throw new LdapException(strMsg, new System.Object[]{host, port}, LdapException.SSL_HANDSHAKE_FAILED, null, ioe); } /* * IOException could be due to a server shutdown notification which * caused our Connection to quit. If so we send back a slightly * different error message. We could have checked this a little * earlier in the method but that would be an expensive check each * time we send out a message. Since this shutdown request is * going to be an infrequent occurence we check for it only when * we get an IOException. shutdown() will do the cleanup. */ if (clientActive) { // We beliefe the connection was alive if (unsolSvrShutDnNotification) { // got server shutdown throw new LdapException(ExceptionMessages.SERVER_SHUTDOWN_REQ, new System.Object[]{host, port}, LdapException.CONNECT_ERROR, null, ioe); } // Other I/O Exceptions on host:port are reported as is throw new LdapException(ExceptionMessages.IO_EXCEPTION, new System.Object[]{host, port}, LdapException.CONNECT_ERROR, null, ioe); } } finally { freeWriteSemaphore(id); handshakeProblemsEncountered.Clear(); } return ; }
/// <summary> Sends an Ldap request to a directory server. /// /// The specified the Ldap request is sent to the directory server /// associated with this connection. An Ldap request object is an /// {@link LdapMessage} with the operation type set to one of the request /// types. You can build a request by using the request classes found in this /// package /// /// You should note that, since Ldap requests sent to the server /// using sendRequest are asynchronous, automatic referral following /// does not apply to these requests. /// /// </summary> /// <param name="request">The Ldap request to send to the directory server. /// </param> /// <param name="queue"> The queue for messages returned from a server in /// response to this request. If it is null, a /// queue object is created internally. /// </param> /// <param name="cons"> The constraints that apply to this request /// </param> /// <exception> LdapException A general exception which includes an error /// message and an Ldap error code. /// /// </exception> /// <seealso cref="LdapMessage.Type"> /// </seealso> /// <seealso cref="RfcLdapMessage.isRequest"> /// </seealso> public virtual LdapMessageQueue SendRequest(LdapMessage request, LdapMessageQueue queue, LdapConstraints cons) { if (!request.Request) { throw new System.SystemException("Object is not a request message"); } if (cons == null) { cons = defSearchCons; } // Get the correct queue for a search request MessageAgent agent; LdapMessageQueue myqueue = queue; if (myqueue == null) { agent = new MessageAgent(); if (request.Type == LdapMessage.SEARCH_REQUEST) { myqueue = new LdapSearchQueue(agent); } else { myqueue = new LdapResponseQueue(agent); } } else { if (request.Type == LdapMessage.SEARCH_REQUEST) { agent = queue.MessageAgent; } else { agent = queue.MessageAgent; } } try { agent.sendMessage(conn, request, cons.TimeLimit, myqueue, null); } catch (LdapException lex) { throw lex; } return myqueue; }
protected abstract bool NotifyEventListeners(LdapMessage sourceMessage, EventClassifiers aClassification, int nType);