// This method is called *only* when cookie verification is done, so unlike with public // Add(Cookie cookie) the cookie is in a reasonable condition. internal void Add(Cookie cookie, bool throwOnError) { PathList pathList; if (cookie.Value.Length > m_maxCookieSize) { if (throwOnError) { throw new CookieException(SR.Format(SR.net_cookie_size, cookie.ToString(), m_maxCookieSize)); } return; } try { lock (m_domainTable) { if (!m_domainTable.TryGetValue(cookie.DomainKey, out pathList)) { m_domainTable[cookie.DomainKey] = (pathList = PathList.Create()); } } int domain_count = pathList.GetCookiesCount(); CookieCollection cookies; lock (pathList.SyncRoot) { cookies = pathList[cookie.Path]; if (cookies == null) { cookies = new CookieCollection(); pathList[cookie.Path] = cookies; } } if (cookie.Expired) { // Explicit removal command (Max-Age == 0) lock (cookies) { int idx = cookies.IndexOf(cookie); if (idx != -1) { cookies.RemoveAt(idx); --m_count; } } } else { // This is about real cookie adding, check Capacity first if (domain_count >= m_maxCookiesPerDomain && !AgeCookies(cookie.DomainKey)) { return; // Cannot age: reject new cookie } else if (m_count >= m_maxCookies && !AgeCookies(null)) { return; // Cannot age: reject new cookie } // About to change the collection lock (cookies) { m_count += cookies.InternalAdd(cookie, true); } } } catch (OutOfMemoryException) { throw; } catch (Exception e) { if (throwOnError) { throw new CookieException(SR.net_container_add_cookie, e); } } }