Windows: Network connections timing out too quickly on temporary connectivity loss

If you have a rather unstable network where you tend to loose connectivity for a short time frequently, you might notice that established connections (e.g. ssh connections using putty) will get lost. You can then immediately reconnect but it’s still a pain.

The issue is not really with the software loosing the connection (e.g. putty) but rather with the Windows network configuration. A single application cannot set the network settings for the whole application or a specific session to prevent this problem. To solve this problem, you will need to tweak a few Windows network settings.

Basically tweaking these settings means increasing the TCP timeout in Windows. This can be done in the registry.

The relevant TCP/IP settings are:

  • KeepAliveTime
  • KeepAliveInterval
  • TcpMaxDataRetransmissions

These parameters are all located at the following registry location: \HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Tcpip\Parameters.

On Windows versions which are not based on Windows NT (i.e. Windows 95, Windows 98 and Windows ME), these parameters are located under: HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\VxD\MSTCP.

KeepAliveTime

The KeepAliveTime parameters controls how long the TCP driver waits until the a keep-alive packet is sent over an idle TCP connection. A TCP keep-alive packet is simply an ACK packet sent over the connection with the sequence number set to one less than the current sequence number for the connection. When the other end receives this packet, it will send an ACK as a response with the current sequence number. These communication is used to make sure that the remote host at the other end of the connection is still available and make sure the connection is kept open.

Since TCP keep-alives are disabled by default, the application opening the connection needs to specifically enable them.

The value is the number of milliseconds of inactivity before a keep-alive packet is sent. The default is 7,200,000 milliseconds (ms) i.e. 2 hours.

Note that the default of 2 hours might be to high in some cases. Having a high KeepAliveTime brings two problems:

  1. it may cause a delay before the machine at one end of the connection detects that the remote machine is no longer available
  2. many firewalls drop the session if no traffic occurs for a given amount of time

In the first case, if your application can handle reconnect scenario, it will take a very long time until it notices the connection is dead and it would have been able to handle it properly if it failed fast.

In the second case, it’s the opposite, the connection is articially closed by the firewall inbetween.

If you encounter one of these cases on a regular basis, you should consider reducing the KeepAliveTime from 2 hours to 10 or 15 minutes (i.e. 600,000 or 900,000 milliseconds).

But also keep in mind that lowering the value for the KeepAliveTime:

  • increases network activity on idle connections
  • can cause active working connections to terminate because of latency issues.

Setting it to less than 10 seconds, is not a good idea except if you have a network environment with with a very low latency.

KeepAliveInterval

If the remote host at the other end of the connection does not respond to the keep-alive packet, it is repeated. This is where the KeepAliveInterval is used. This parameter determines how often this retry mechanism will be triggered. This is basically the wait time before another keep-alive packet is sent. If at some point in time the remote hosts responds to the keep-alive packet, the next keep-alive packet will be again sent based on the KeepAliveTime parameter (assuming the connection is still idle).

The value is the number of milliseconds before a keep-alive packet is resent. The default is 1,000 milliseconds (ms) i.e. 1 second. If the network connectivity losses sometimes last a few minutes, it’d make sense increasing this parameter to 60,000 milliseconds i.e. 1 minute.

TcpMaxDataRetransmissions

Of course this retry process cannot go on for ever. If the connection is not only temporarily lost but lost for good, then the connection needs to be closed. This is where the parameter TcpMaxDataRetransmissions is used. This parameter defines the number of keep-alive retries to be performed before the connection is aborted.

The default value is to perform 5 TCP keep-alive retransmits. If you experience network instability and lose connections too often, you should consider increasing this value to 10 or 15.

Note that starting with Windows Vista, this parameter doesn’t exist anymore and is replaced by a hard-coded value of 10. After 10 unanswered retransmissions, the connection will be aborted. But you can still control the time frame which a connection could survive a temporary connectivity loss by adapting the KeepAliveInterval parameter.

Also note that this parameter only exists in Windows NT based versions of Windows. On old systems running Windows 95, Windows 98 or Windows ME, the corresponding parameter is HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\VxD\MSTCP\MaxDataRetries.

Summary

Tweaking the parameters above, one can configure the Windows TCP driver so that connections can survive small connectivity losses. Remember that after changing these settings, you’ll need to reboot the machine (it’s Windows after all…).

If you cannot modify TcpMaxDataRetransmissions because you have a newer version of Windows, you can still reach the same results by increasing KeepAliveInterval instead.

Also note that issues with lost connections in unstable networks seems to especially affect Windows Vista and later. So if you move from Windows XP to let’s say Windows 7 and you experience such issues, you should first add the KeepAliveTime  and KeepAliveInterval parameters to the registry, reboot, check whether it’s better and possibly increase the value of KeepAliveInterval if required.

All parameters above should be stored in the registry as DWORD (32bit value).

404 Error: /eyeblaster/addineyev2.html

While looking at the content access statistics in Google Analytics, I’ve noticed that a few of them access a page with the URL /eyeblaster/addineyev2.html. Since I was pretty sure I didn’t have such a page I first thought that my site might have been hacked and checked this page. It led me to the 404 error page. So this URL didn’t exist but some of my visitors were redirected to it. The traffic to this page was not so high (never more than 5 page views a day) but I could see that this added up to 25 page views since mid of February.

Next step was to find out where these visitors were coming from. The navigation summary in Google Analytics for this page looks like this:

Navigation Summary

So half of the visitors came from a previous page and half from outside. The distribution of previous pages was pretty random, so it is definitely not related to specific pages:

Previous Page Path

But actually the important most visitors leave my blog once redirected. Googling for this issue, I found a Google support page:

If you are trafficking an EyeBlaster Flash creative as a 3rd-party tag, you will need to put the addineyev2.html file to www.example.com/eyeblaster/addineyev2.html

The code for addinexev2.html can be found on adopstools.com. It’s basically just loading a JavaScript file:

<HTML>
<HEAD>
</HEAD>
<BODY style=margin:0;padding:0>
<SCRIPT src="http://ds.eyeblaster.com/BurstingScript/addineye.js">
</script>
</BODY>
</HTML>

If you add this HTML page, you should also make sense to prevent search engines from indexing it by adding the following to your robots.txt:

Disallow: /eyeblaster
Disallow: /addineyeV2.html

Or by adding the following metatag to the head section of this HTML page:

<meta name="robots" content="noindex" />

But since I didn’t feel confortable adding such a webpage to my site (especially since it’s just loading some JavaScript from a third party site), I looked for another solution. If the script was actually hosted by Google I might have trusted it but it’s not the case.

Looking at the referenced JavaScript file, I found out it seems to be related to the MediaMind ad network and googling for it also showed that Eyeblaster rebranded as MediaMind. So an alternative to adding the HTML file above to your website is to block ads from this network. Actually a network which forces you add files to your site (assuming you can add files at all) should actually be blocked by default by Google. But since they haven’t done it, we’ll have to do it manually.

To block this network, you have to go to Adsense, click on Allow & block ads, type “mediamind” in the search box. You’ll see something like this:

allow block MediaMind ad network

Then click on the left side button for each of these networks to block them:

block MediaMind ad network

Now you shouldn’t get these ads which end up redirecting your users to this non-existing HTML page and you’ll display ads from networks which behave better. I’m suspecting that other networks might also be using this script, so I’ll have to monitor this and find out which other ad networks I’ll have to block.

Visual Studio 2012: mspdb110.dll is missing when executing editbin.exe

I was having some issues using an OCX in an old application I had recompiled using Visual Studio 2012. One thing I found is that it might be related to a compatibility issue with Data Execution Prevention (DEP). Since I couldn’t recompile the OCX and didn’t have direct access to the linker settings, I went for using editbin.exe to apply a /NXCOMPAT:NO. But when I ran the following:

C:\Users\benohead>"c:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\bin\editbin.exe" /NXCOMPAT:NO myfile.exe

I got a system error from link.exe saying:

The program can’t start because mspdb110.dll is missing from your computer. Try reinstalling the program to fix this problem.

The cause for this error is that I executed the command in the wrong DOS prompt. Not the one where I had executed vcvars32.bat. So I just executed vcvars32.bat:

"c:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\bin\vcvars32.bat"

And gave it another try. Now no error message was displayed.

WordPress: Network-wide plugin settings

When developing a plugin, which will be used on single site, as well as multi-site, there are two ways of supporting multi-site deployments:

  1. The plugin is activated per site and provides per-site settings only.
  2. The plugin can be activated for the whole network and provides network-wide settings

I’m currently working on a plugin which needs to support both scenarios. The first scenario is pretty straight forward. But the second one is a little bit trickier.

  • Proper support of the network activation
  • Activation for new sites
  • Network-wide settings
  • Proper support of the network deactivation

Proper support of the network activation

To activate the plugin in a multisite environment, you’ll need go through all the blogs and activate them individually e.g.:

register_activation_hook( __FILE__, 'my_plugin_activate' );

function my_plugin_activate($network_wide)
{
	global $wpdb;

	if (function_exists('is_multisite') && is_multisite() && $network_wide) {
		$current_blog = $wpdb->blogid;
		$blogs = $wpdb->get_col("SELECT blog_id FROM $wpdb->blogs");
		foreach ($blogs as $blog) {
			switch_to_blog($blog);
			my_plugin_activate();
		}
		switch_to_blog($current_blog);
	} else {
		my_plugin_activate();
	}
}

If we are in a multisite environment but the plugin is only activated to for a blog, a normal activation is performed. Otherwise we fetch the list of all blogs and activate them one by one before reverting to the current blog.

Note that you should not use restore current blog() to get back to the original blog since it will revert to the blog active before the last switch_to_blog(). So if switch_to_blog() is called twice it will not revert to the blog which was active before this all started.

Activation for new sites

When a new blog is added, you’ll need to specifically activate the plugin for this blog since this blog was not present, when the activation occurred.

add_action( 'wpmu_new_blog', 'activate_new_blog' );
 
function activate_new_blog($blog_id) {
    global $wpdb;
 
    if (is_plugin_active_for_network('plugin_name/plugin_main_file.php')) {
	switch_to_blog($blog_id);
	my_plugin_activate();
	restore_current_blog();
    }
}

So first we check whether the plugin was activated for the whole network. If it is the case, we switch to the new blog, activate the plugin for this blog and switch back to the previous blog. Here it is fine to use restore_current_blog() since we only use one switch_to_blog().

Network-wide settings

In single site environment, you would use the functions get_option() and update_option() to respectively read and write your plugin settings. In a multi-site environment, you should rather use the get_site_option() and update_site_option() functions instead.

So instead of:

get_option('my_settings', array())
...
update_option( 'my_settings', $settings );

Use:

get_site_option('my_settings', array())
...
update_site_option( 'my_settings', $settings );

When registering your settings page, instead of using options-general.php as parent slug, when calling add_submenu_page, if your plugin has been network activated, you’ll need to add the submenu page using settings.php as parent slug.

Also when linking to your settings page (i.e. from the plugins list), in a single site environment, you’d do it this way:

<a href="options-general.php?page=my_settings">Settings</a>

But to link to the network settings page, you’ll need to use the following

<a href="settings.php?page=my_settings">Settings</a>

The hook for adding the link is also different. Instead of adding a filter for ‘plugin_action_links_pluginname_pluginfile’, you’ll have to add a filter for ‘network_admin_plugin_action_links_pluginname_pluginfile’.

Also the hook to use to call your registering function is different, instead of adding an action to the ‘admin_menu’ hook, you should add an action to the ‘network_admin_menu’ hook in a network activation scenario.

In your settings page, when in a single site environment, you can use the settings API and do not need to update your settings manually, by using options.php as form action:

<form method="post" action="options.php">

For network-wide settings it’s not so easy. There is no direct equivalent to options.php for such settings. You will need to direct to edit.php and provide an action name which will be linked to one of your functions where you will update the settings. Here the registration and definition of this function:

add_action('network_admin_edit_my_settings', __FILE__, 'update_network_setting');

function update_network_setting() {
	update_site_option( 'my_settings', $_POST[ 'my_settings' ] );
	wp_redirect( add_query_arg( array( 'page' => my_settings, 'updated' => 'true' ), network_admin_url( 'settings.php' ) ) );
	exit;
}

Of course instead of my_settings, you should use the name of your settings. The name of the action hook is network_admin_edit_ followed by an action name which will be used as parameter to edit.php in the form definition e.g.:

<form method="post" action="edit.php?action=my_settings">

Of course, since you want to support both the normal and the network activation scenarios, you’ll have to use is_plugin_active_for_network() to figure out in which scenario you are and trigger the appropriate logic.

Proper support of the network deactivation

For the deactivation, you need to do exactly the same you’ve already done for the activation i.e.:

register_deactivation_hook( __FILE__, 'my_plugin_deactivate' );

function my_plugin_deactivate($network_wide)
{
	global $wpdb;

	if (function_exists('is_multisite') && is_multisite() && $network_wide) {
		$current_blog = $wpdb->blogid;
		$blogs = $wpdb->get_col("SELECT blog_id FROM $wpdb->blogs");
		foreach ($blogs as $blog) {
			switch_to_blog($blog);
			my_plugin_deactivate();
		}
		switch_to_blog($current_blog);
	} else {
		my_plugin_deactivate();
	}
}

function my_plugin_deactivate()
{
	//deactivate the plugin for the current blog
}

Of course in a network-wide deactivation scenario, you may want to add some additional cleanup after the plugin has been deactivated for all blogs.

Conclusion

So supporting all three scenarios (single site, multisite with per blog activation and multisite with network activation) is not so difficult. The only tricky part is handling network-wide settings. Unfortunately, the settings API does not help you much here. But once you’ve done it for a plugin, it’s just a matter of copy&paste.

Note that if you do not perform anything special as part of your activation, you do not need to handle the multisite activation since WordPress will activate the plugins appropriately. It is only required if your plugin does some additional magic since WordPress will not call you for each blog.

WordPress: Running multisite on different port

Since I’m maintaining a few WordPress plugins I wanted to have a local installation where I can also make sure that new versions of the plugins also behave well in a multisite environment (site network). Unfortunately, I cannot use ports 80 and 443 since I need them for some other projects I’m working on (using IIS). So my local apache server runs on ports 8080 (http) and 8443 (https).

The problem is that this is not supported by WordPress. You need to run on ports 80 and/or 443. Otherwise WordPress won’t let you create a site network and you’ll get a message saying:

You cannot install a network of sites with your server address.
You cannot use port numbers such as 8080.

A single site installation of WordPress works fine on port 8080 but for some reason, it isn’t support for WordPres Site Networks… Well, that’s not a reason not to use it :-)

Since it’s all PHP, you can easily just fix it. Of course, you need to keep in mind that any update of WordPress might remove the changes and you’ll need to do it all again. But since it’s just a test installation, it’s not a problem for me.

So, to find out how to fix it, we first need to find out where this message is displayed. Using grep, you can quickly find that it comes from the function network_step1 in wp-admin\network.php. The relevant piece of code looks like this:

if ( ( false !== $has_ports && ! in_array( $has_ports, array( ':80', ':443' ) ) ) ) {
	echo '<div class="error"><p><strong>' . __( 'ERROR:') . '</strong> ' . __( 'You cannot install a network of sites with your server address.' ) . '</p></div>';
	echo '<p>' . sprintf( __( 'You cannot use port numbers such as <code>%s</code>.' ), $has_ports ) . '</p>';
	echo '<a href="' . esc_url( admin_url() ) . '">' . __( 'Return to Dashboard' ) . '</a>';
	echo '</div>';
	include( ABSPATH . 'wp-admin/admin-footer.php' );
	die();
}

If you use an extra :80 or :443, WordPress will not complain but it will if it is another port number. So in order not to get this error message, you just need to add the ports you need to the list, replacing:

if ( ( false !== $has_ports && ! in_array( $has_ports, array( ':80', ':443' ) ) ) ) {

by:

if ( ( false !== $has_ports && ! in_array( $has_ports, array( ':80', ':443', ':8080', ':8443' ) ) ) ) {

Of course, I assumed there was a reason why only ports 80 and 443 were supported. So I searched in the code for 80 and 443 and found this in wp-includes\ms-settings.php:

if ( substr( $domain, -3 ) == ':80' ) {
	$domain = substr( $domain, 0, -3 );
	$_SERVER['HTTP_HOST'] = substr( $_SERVER['HTTP_HOST'], 0, -3 );
} elseif ( substr( $domain, -4 ) == ':443' ) {
	$domain = substr( $domain, 0, -4 );
	$_SERVER['HTTP_HOST'] = substr( $_SERVER['HTTP_HOST'], 0, -4 );
}

In a previous version of this post I was adding some code for ports 8080 and 8443 but I realized it was actually making things worse. The only purpose of this piece of code is to remove unnecessary port numbers which are not relevant for comparing domain names. But ports 8080 and 8443 are relevant (https://benohead.com:8443 doesn’t point to the same web server as https://benohead.com, but https://benohead.com:443 does).

With the changes above I could create the site network. But when I tried to login, I was redirected to the IIS, to http://localhost/wordpress/wp-login.php instead of http://localhost:8080/wordpress/wp-login.php. Since I couldn’t find anything in code which would explain this, I had a look at the wp_options. And saw that the siteurl option contained http://localhost/wordpress/ instead of http://localhost:8080/wordpress/. So I just updated it in MySQL using the following SQL statement:

UPDATE `my_wordpress_db`.`wp_options` SET `option_value` = 'http://localhost:8080/wordpress/' WHERE `wp_options`.`option_name` = 'siteurl';

And tried again. And this time I got to the right login page ! Remember to replace “my_wordpress_db” by the name of your WordPress database.

I then noticed that there were still some links pointing to http://localhost/wordpress. Finally I saw that the “home” option in wp_options was still pointing to the wrong URL. After fixing it, everything looked fine:

UPDATE `my_wordpress_db`.`wp_options` SET `option_value` = 'http://127.0.0.1:8080/wordpress/' WHERE `wp_options`.`option_name` = 'home';

So now everything was working fine, the admin page, the blog post/pages. But then I realized that when creating a new site, I saw “localhost:8080″ in the UI but it was saving localhost8080 instead. So something was removing the colon. And I found the following in the function wpmu_create_blog in wp-includes\ms-functions.php:

$domain = preg_replace( '/\s+/', '', sanitize_user( $domain, true ) );

With the second parameter is true, only alphanumeric characters plus these: _, space, ., -, *, and @ are returned. Of course, one solution would be to add colon to the list but then it would allow usernames to contain colons as well. So I ended up just setting the second parameter to false, or rather commenting it out, since false is the default:

$domain = preg_replace( '/\s+/', '', sanitize_user( $domain/*, true*/ ) );

Now everything seems to be working.

While looking for a solution, I did find a few links explaining how to do it in version prior to WordPress 3.7. But I needed it for WordPress 3.9.1. So I had to find a solution by myself. Of course I have only tested it on WP 3.9.1 and haven’t checked when was last time these pieces of code were changed. So it might work on WP 3.7 and WP 3.8 as well but I cannot guarantee anything.

Visual C++: module unsafe for SAFESEH image, unable to generate SAFESEH image

Using Visual Studio 2012, I was building from the command line a software which was built until now using an older version (guess it was Visual Studio 2005). There were of course many things I had to change in the code itself (so much for portability…). And of course I had to upgrade the project in the solutions to VS2012 (using the devenv /upgrade command).

After converting the projects and modifying the code, I got the following error messages on a few projects:

error LNK2026: module unsafe for SAFESEH image.

fatal error LNK1281: Unable to generate SAFESEH image.

This means that the linker was started with the option meaning /SAFESEH “image has safe exception handlers” (also note that we only got this because we’re still building 32bit targets). The error occurs because some input modules were not compatible with the safe exception handlers feature of the linker. In our case it was some third party lib files for which I did not have the source code. These lib files are not be compatible with safe exception handlers is because they were created with an older version of the Visual C++ compiler.

But this is easy to fix. You just need to tell the linker not to produce an image with a table of safe exceptions handlers even if it thinks that all modules are compatible with the safe exception handling feature.

If you work in the Visual Studio Editor, you can right-click on your DLL project, go to Properties > Linker > Advanced and set “image has safe exception handlers” to No.

If like me you’re working from the command line, you can edit the .vcxproj file by opening it and searching for the <link> tags. Add the following to each <link> tag (there will be one per target e.g. one for debug and one for release):

<ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>

It doesn’t matter where exactly you add it, it just needs to be between <link> and </link>.

If you call the linker yourself, you can also add /SAFESEH:NO to the command line.

After making this change, you can build your project again and the error will be gone.

OleViewer: STG_E_FILENOTFOUND and IDataObject interface viewer only supports IID_IDataObject

I had some problems loading a type library (TLB file) when building a Visual C++ project, so I wanted to have a look at the TLB file using the OleViewer. So I started the OleViewer as Administrator from C:\Program Files\Microsoft SDKs\Windows\v7.1\Bin\x64. When opening the TLB file I got the following error message:

LoadTypeLib(my tlb file) failed.
STG_R_FILENOTFOUND ($80030002)

The issue here was that I started the 64bit version of the OleViewer. With the 32bit version (present directly in C:\Program Files\Microsoft SDKs\Windows\v7.1\Bin), this error was gone, so it could actually load the file but I got another error message:

IDataObject interface viewer only supports IID_IDataObject

Solving this was easy but kind of confusing. I went to the View menu, unchecked “Expert Mode” then opened the TLB file. And the error message was gone. After that I checked it again but could still open the TLB file. Eveb after closing the OleViewer and opening it again, I was able to load the TLB file.

I’m still not 100% sure what happened here… Another thing I did after removing the Expert Mode and before reopening my TLB file was to open a few object classes in the tree on the left. At least of them was the Microsoft Web Browser (under Controls). So if unchecking the Expert Mode alone doesn’t help, you could try this.

It looks like the error message I got above means that iviewers.dll in-process server was not properly registered. The OleViewer uses iviewers.dll to parse the type library. Somehow after the things I’ve done above, the registration was fine. Of course if it still doesn’t work for you, you can try registering it yourself using regsvr32 iviewers.dll.

Somewhere inbetween I’ve also try using but also had a problem with the same TLB file (also it worked for others). After the problem was solved with OleViewer, OleWoo was also able to open the TLB file. So I guess OleWoo parses the TLB the same way OleViewer does.

And actually after that Visual Studio 2012 wasn’t complaining anymore about the TLB file. Before that I got the following error message on the line where I import the TLB file:

error C1084: Cannot read type library file: ‘my tlb file’: Error loading type library/DLL.

So it looks like Visual Studio had the same issue with iviewers.dll as OleViewer and OleWoo but unfortunately only said it couldn’t load the type library instead of giving me a more precise error message…

Even if I don’t really get what happend here, I’m glad it’s solved :-)