Sunday, May 31, 2009

Bug in Media Player causes shutdown of Internet in China.

China’s Internet Service Providers (ISPs) do not like to talk to each other. the vast majority (90% in 2006) of customer complains received by the Ministry of Information Industry is about super slow interconnectivity of the two major ISPs, China Telecom and China Netcom, and people’s workarounds of the interconnectivity problem have side effects, like the recent Internet outrage caused by the Baofeng Media Player.

Here is a little background. The interconnectivity problem arose after the spin-off of China Netcom from China Telecom 2002. Before the split, China Telecom had a monopoly on network bandwidth, and local ISPs could not really compete with China Telecom because they had to rent China Telecom’s bandwidth for non-local services. The government ordered a split of the company after most of local ISPs went out of business, and created the interconnectivity problem.

After the spin-off, the China Telecom network is now split into two subnets, China Telecom in south and China Netcom in north. The two companies employed some anticompetitive tactics, including exclusive service agreements with estate developers and not keeping up with growing demand of interconnectivity between major networks. In 2006, the only bridge between them was a connection point at Beijing, which was often so overwhelmed that it was usually slower than routing though a USA network or switching to China Mobile’s CDMA wireless network.

In fact, the majority of connectivity was done by businesses. With ISPs reluctant to connect each other themselves, the only solution was to connect both networks and double the connectivity expense. At the beginning, the users were directed to ISP-specific addresses like http://chinatelecom.example.com in the China Telecom network, and http://chinanetcom.example.com in the China Netcom network. The problem was, users often didn’t know what their ISP is when they are not visiting Internet at home. Soon ISP-specific domain name service (DNS) server were created to direct visitor to the the address inside the visitor’s network. Now the user can use http://www.example .com and the DNS will decide which address the user will be visiting based on the user’s network. The free, personal financed DNSPod is this kind of DNS service.

Unfortunately, several DNS servers of DNSPod were hit by a distributed denial-of-service (DDOS) attack on the night of May 18. DNSPod’s owner did not think the attack was serious, because he dealt with larger attacks before. However, the DNS server China Telecom shut-off this time was hosting a web site used by the Baofeng Media Player, which manifested the DNS outrage to a much greater magnitude.

There was no explanation why the Baofeng Media Player’s company, a multi-million dollar investment with a self-claimed user base of 200 million , is using a free (*read* no warranty of any kind, agreed not liable to damage before using) DNS service. However, the greater mistake was that the Baofeng Media Player’s advertisement downloading service was programmed to go through each server on its server list until it gets an answer. When the ISP’s local DNS cache pointing to the downed DNSPod server expired, the requests to find servers put almost all DNS servers in China under a DDOS attack . At the attack’s peak, Baofeng Media Player’s DNS requests occupied 40% of China Telecom’s total bandwidth. A DDOS attack targeting a specific domain now transformed into a DDOS attach on almost all DNS servers in China, which slowed down the Internet in China to a crawl.

After a day of network outrage, there are lessons to be learned , from programming errors to doubtful business tactics. One thing is for sure, Baofeng Media Player’s advertisement downloading service is the one to blame for this disaster. However, Baofeng Media Player is not the first software with bugs, nor will it be the last one. China ISPs need to think about how to avoid this problem in the future, the sooner the better.

Friday, May 29, 2009

Not sure what is going on at Microsoft Connect

An item I submitted to Microsoft connect changed 3 times at 1:34 am this morning

The following feedback item you submitted at Microsoft Connect has been updated:
The following fields or values changed:
Field Status changed from [Active] to [Resolved]
Field Resolution changed from [Not Set] to [Fixed]

The following feedback item you submitted at Microsoft Connect has been updated:

he following fields or values changed:
Field Status changed from [Active] to [Resolved]

The following feedback item you submitted at Microsoft Connect has been updated:

The following fields or values changed:
Field Status changed from [Resolved] to [Active]

Another item changed 5 times yesterday

The following feedback item you submitted at Microsoft Connect has been updated:

Field Status changed from [Active] to [Resolved]
Field Resolution changed from [Not Set] to [Not Reproducible]

The following feedback item you submitted at Microsoft Connect has been updated

The following fields or values changed:
Field Status changed from [Resolved] to [Closed]

The following feedback item you submitted at Microsoft Connect has been updated:

Field Status changed from [Closed] to [Active]

 

The following feedback item you submitted at Microsoft Connect has been updated:

Field Status changed from [Resolved] to [Closed]

The following feedback item you submitted at Microsoft Connect has been updated:

Field Status changed from [Active] to [Resolved]
Field Resolution changed from [Not Reproducible] to [Fixed]

Conclusion: the operator update connect feedbacks in the same way I wrote Wikipedia articles. Stay up after midnight and have a lot of revisions, some good.

Tuesday, May 19, 2009

the Windows Server 2008 SP2 and Windows Vista SP2 Beta program has concluded.

Nice run

uninstalling pre-release SP and installing the RTM version…

Sunday, August 05, 2007

AutoComplete with DataSource

Download the code for this article (22KB)

.Net 2.0 introduced autocompletion in TextBox and ComboBox. It is obvious that autocomplete is not very useful when the number of options is small. However, when your option becomes too many, pre-filling of all options to an AutoCompleteStringCollection becomes impractical, especially when your data comes from a remote computer. An alternative is to replace the AutoCompleteCustomSource in a TextChanged event, however, users are getting random AccessViolationException when trying to replace it.  In this article I will demonstrate another alternative, using a BindingSource as the data source of options and bypassing the .Net framework and call the underline Windows API directly.

The first thing I need to do is to port the APIs to managed code. The autocompletion API is exposed as a COM object, so I need to write managed version of its interfaces:

    [ComImport]
    [InterfaceType(ComInterfaceType::InterfaceIsIUnknown)]
    [Guid("EAC04BC0-3791-11D2-BB95-0060977B464C")]
    [SuppressUnmanagedCodeSecurity]
    interface  class IAutoComplete2
    {
             [PreserveSig] int Init(
            HandleRef hwndEdit,
            IEnumString^ punkACL,
             String^ pwszRegKeyPath,           
            String^ pwszQuickComplete
        );
        void Enable( [MarshalAs(UnmanagedType::Bool)] bool value);

        int SetOptions(int dwFlag);

        void GetOptions([Out]IntPtr pdwFlag);
    };
Second, I need to create the autocomplete object and query the IAutoComplete2 interface:

       Type^ autoCompleteType = Type::GetTypeFromCLSID(CLSID_AutoComplete);
        try{
            autoComplete2 =(IAutoComplete2^)(Activator::CreateInstance(autoCompleteType));
        }
        catch(Exception^ e)
        {
            Marshal::ReleaseComObject(autoComplete2);
            autoComplete2 = nullptr;
        }

Third, I need to bind it to an TextBox control:

    bool AutocompleteBindingSource::Bind()
    {
        if (nullptr==this->autoComplete2)
            return false;
        try
        {
            this->autoComplete2->SetOptions((int)ControlToBind->AutoCompleteMode);
            this->autoComplete2->Init(
                HandleRef(ControlToBind,ControlToBind->Handle),
                this,
                String::Empty
                ,String::Empty);
            return true;
        }
        catch(Exception^e)
        {
            return false;
        }

    }

Finally, I need to implement IEnumString to provide a list of options. Luckily, .Net has declared this interface, so I don't need to port it to managed code, however, I still need to write my binding code in my implementation of IEnumString.

    void AutocompleteBindingSource::Reset()
    {
        this->current = 0;
        if(BindingSource!=nullptr)
            this->size=BindingSource->Count;
    }

        int AutocompleteBindingSource::Next(
        int celt, [Out, MarshalAs(UnmanagedType::LPArray, ArraySubType=UnmanagedType::LPWStr, SizeParamIndex=0)] array<String^>^ rgelt, IntPtr pceltFetched)
    {
        if (celt < 0)        {
            return E_INVALIDARG;
        }
        int index = 0;
        while ((this->current < this->size) && (celt > 0))
        {
            Object^ item=this->BindingSource->default[this->current];

            bool useDisplayMember=false;

            if(!String::IsNullOrEmpty(DisplayMember))
            {
                ICustomTypeDescriptor^ customTypeDescriptor=dynamic_cast<ICustomTypeDescriptor^>(item);
                if(customTypeDescriptor!=nullptr)
                {
                    PropertyDescriptorCollection^ propertyDescriptorCollection=
                        customTypeDescriptor->GetProperties();
                    if(propertyDescriptorCollection!=nullptr)
                    {
                        PropertyDescriptor^ propertyDescriptor=propertyDescriptorCollection->default[DisplayMember];
                        if(propertyDescriptor!=nullptr)
                        {
                            rgelt[index] = propertyDescriptor->GetValue(item)->ToString();
                            useDisplayMember=true;
                        }
                    }
                }
            }

            if(!useDisplayMember)
            {
                if(item!=nullptr)
                {
                    rgelt[index] = item->ToString();
                }
            }
            this->current++;
            index++;
            celt--;
        }
        if ((pceltFetched != IntPtr::Zero))
        {
            Marshal::WriteInt32(pceltFetched, index);
        }
        if ((celt != 0))
        {
            return 1;
        }
        return 0;

    }

Here the DisplayMember property is the name of the property in the data source to be displayed. If the property specified by the value of the DataMember property does not exist, I use ToString to get a text representation of the current item in the data source.

You may want to ask, where is the filtering code? Well, that is implemented by BindingSource class.

        System::Void FormTest::textBoxDemo_TextChanged(System::Object^  sender, System::EventArgs^  e)
        {
            if(String::IsNullOrEmpty(textBoxDemo->Text))
                bindingSourceAutoComplete->Filter=nullptr;
            else
                bindingSourceAutoComplete->Filter=
                    String::Format("{0} LIKE '{1}%'"
                    ,dataSetDemo->Tables[0]->Columns[0]->Caption
                    ,textBoxDemo->Text);
            autocompleteBindingSource1->Reset();
        }

The BindingSource class checks the data source to see if they support the IBindingListView. If IBindingListView is supported, the BindingSource class delegates sorting and filtering to the data source.  In this sample, the data source of the BindingSource object is a DataSet, and the DataMember of BindingSource object is the name of the first table , so BindingSource creates a DataView as its data source. The DataView class implements IBindingListView and filters its data using expressions parsed from the filter string. In reality, the data source could be a business object that implements IBindingListView and supports filtering and sorting with stored procedures.

This sample does not consider compound autocomplete object support. If you want to get your options from multiple sources, you need to use IObjMgr to add sources to the autocomplete object.

Reference

Thursday, October 26, 2006

how JScript cleans up

From http://msdn.microsoft.com/msdnmag/issues/01/05/web/

JScript uses a mark-and-sweep garbage collector with a variety of heuristics used to determine when to run garbage collection. The JScript garbage collector works like this:

  1. When the script engine is shut down, garbage is collected.
  2. When 256 variants, or more than 64KB of strings, or more than 4096 array slots have been allocated, the garbage collector sets a flag that says collect soon.
  3. Whenever a new statement is executed or the script debugger starts, that flag is checked, and if it is set, a collection is done.

There is an undocumented JScript function called CollectGarbage that forces a garbage collection. This is for testing purposes only—do not ship code that calls this function. It is a poor programming practice to write code in JScript that depends on garbage collections being done at particular times. If you need predictable garbage collection, use a language that supports it (like Visual Basic® or VBScript). Note that all of this is the implementation detail of the engine and should not be relied upon because it may change in the future. Note also that the version of JScript supported by Microsoft® .NET will use the .NET Framework garbage collector, a multigenerational mark-and-sweep collector.
And remember, if you want a deterministic-lifetime app, use a deterministic-lifetime language like C++, Visual Basic 6.0, or VBScript; not an indeterministic-lifetime language like JScript, Scheme, or Java. If you're writing a program that depends on being able to have a deterministic object lifetime, JScript is not the right tool for the job. Trying to make it a deterministic-lifetime language will just create headaches down the road.

From http://www.faqts.com/knowledge_base/view.phtml/aid/10251

This function uses ActiveX to get a forms input into a spreadsheet cell.

function xlWrite(r,c) {
var xlApp, xlSheet;
xlApp = new ActiveXObject("Excel.Application");
xlApp.Visible = true;
xlApp.Workbooks.Add();
xlSheet = xlApp.ActiveSheet;
xlSheet.Cells(r,c).Value = frm.txt.value;
xlSheet.SaveAs("C:\\xlText.xls");

Note that Excel has a bug and doesn't shut down after calling the
Quit() method when automating from JScript. To work around this
problem, the CollectGarbage() method is used to force JScript's garbage
collection to occur almost immediately.

xlApp.Quit();
xlApp = null;
setTimeout("CollectGarbage()",1);
}
Beware of garbage collector. If your declare your DHTML objects inside a function, it may be garbage collected when it goes out of scope and disappears.