SUP? I’m good, I have ADC, Ya Know?

One of the most interesting features in ADC is the ability to signal that the client or hub support some feature, and that others can take advantage of that. This is not all too different from NMDC’s (hacked) $Supports. In fact, they represent the same thing; The ability to support a particular feature. These features should only be things that are being transmitted between clients and/or to the hub, since it’s no use signaling that you have the ability to have a Notepad built in the client.

There are three ways a client will signal it supports something.
1) To the hub (usually/probably in the initial connection state). Here, hubs may (should) decide to allow clients that support a particular feature the hub owner(s) would want users to have. The hub may restrict clients if the clients signal they support a particular feature, or if they lack the support of another. It’s all very “hey, I support this and that. May I enter?” If the hub sees the clients supporting a feature the hub doesn’t know about, it can/should let the clients through. With ‘should’ in that sentence, the clients have the ability to be up to date with features, while the hub could be extremely old and without any piece of knowledge about the new features. In NMDC, hubs and clients need to be updated when one either are updated with a new feature.
This part is signaled as HSUP ADfeaturename ADanotherfeature. All clients and hubs must support BASE, which is the ADC draft. Every feature must be 4 characters, and all upper case.
2) To all clients, in a broadcast manor (usually/probably in the connection stage). This is signaled in the INF, where you send BINF SUfeature, otherfeature,nfeature. (B == broadcast) As far as I know, there is no way to signal to specifically add or remove a feature in this way, so the client probably need to send the entire feature list. Again, this must be 4 characters and all upper case.
3) To specific client (usually in the connecting stage for a download). Here, you can send the SUP list or the INF list, which ever you find appropriate.

Sometimes, the user (or client) may want to say “hey, I don’t want to support/use this feature anymore, so don’t query me about it”. A simple checkbox in the client/hub can suffice for the meaning of “enable/disable this feature”. This is an interesting feature (in ADC) that NMDC doesn’t. NMDC has no way of saying (while connected to the hub) that the client doesn’t want to support a particular feature. But in ADC, the client can signal that it doesn’t want to support something any time it want to. (Whether the hub will approve of removing a that feature is something else. It may get you kicked out of the hub.)
Clients (and hubs) can signal that it has stopped supporting a feature by using HSUP RMremovethisfeature.

So, let us create a feature, and see what we need to do. Say we want a way to tell people when (you’re) searching that you also want to receive back the entered e-mail the other user got. (Why? Well, I don’t know…)
Now, let us call it SINF (“search inf”), where we have also abstracted it so much that one should be able to “want” anything from the INF. Eg, the client version or the e-mail. So we signal SUP ADSINF (for the hub), and then INF SUSINF (for the clients). Now, we also say that everyone that is able to send the request, should also be able to send the result back. (So we don’t have to come up with another command. Now, whenever we send a search we also signal “EM1”, meaning “give me the information in EM. (EM == e-mail). The other clients that support the SINF feature, will then send back “EMthis.is.my@email.com”. What is particularly interesting here is that the hub doesn’t have to send the EM1 to every client in the hub. The hub can keep a list of everyone that support SINF, and only forward that part to those clients. There’s no reason a client should get EM1 if it doesn’t even comprehend what that means. A little more hub work == less bandwidth cost for many. (The client, if it see something it doesn’t know, will anyway only discard it.)

There aren’t any particular restriction when signaling. You have to make sure the extension and/or command name is unique, since otherwise it could lead to clashes. And of course that everything transmitted in ADC (command names etc) are always in upper case. Beyond that, what restricts the programmer is the amount of combinations for feature name (A-Z, 0-9) and the programmer’s imagination.

(Yes, I know, I used lower case for the above features, but it didn’t look so nice with upper case, and the blog is weird when it comes to certain brackets…)

Don’t forget that you can make topic suggestions for blog posts in our “Blog Topic Suggestion Box!”

Visual Studio 2005

As of the next release of DC++, the project files will be incompatible with Visual Studio 2003 (see: svn 677). For many developers, myself included, this means an upgrade. Previously, Microsoft published Visual C++ .NET [2002] and Visual C++ .NET 2003, which were priced at around $100, and would compile DC++ just fine. For their “2005” product line, they dropped the standalone C++ environment, leaving me in a bind. It turns out that owners of Visual C++ .NET 2002/2003 are qualified to purchase the Visual Studio Standard 2005 upgrade, which retails for $200. I just ordered received my copy and if this post isn’t updated, you can safely assume it works for compiling DC++.

The Visual Studio Express 2005 package is free, but it doesn’t include ATL. The above is the least expensive way to compile DC++, really.

Don’t forget that you can make topic suggestions for blog posts in our “Blog Topic Suggestion Box!”

Compiling DC++ with Visual Studio 2003

This guide is about compiling DC++ on Windows, with Visual studio 2003.

To compile DC++, you will need a few things.

First, download the DC++ source, and unpack it in C:\dcplusplus\dcplusplus696\. (So you got C:\dcplusplus\dcplusplus696\windows, C:\dcplusplus\dcplusplus696\client etc.)

Download STLport, and unpack it in C:\dcplusplus\STL so you got C:\dcplusplus\STL\config etc.

Download WTL and unpack it in C:\dcplusplus\WTL so you got C:\dcplusplus\WTL\include etc.

Download the latest SDK, or get the natupnp.h file from Bugzilla. Place it in C:\dcplusplus\natupnp\. (I think I have it in some Visual Studio include path, but this should work fine too.)

Download YaSSL and unpack it in C:\dcplusplus\YaSSL so you got C:\dcplusplus\YaSSL\certs etc.

Download Python and install it. (I got mine in the default folder)

Enter C:\dcplusplus\dcplusplus696\. Open up DCPlusPlus.rc and change the line #include “wtl\\atlres.h” to #include “atlres.h”

Open up the workspace (DCPlusPlus.sln)

Under the Tools menu, press Options.

Go to Projects and then VC++ Directories.

Under ‘Show directories for’ select ‘Include files’.

Add the STL folder, WTL\include folder, YaSSL folder and then the natupnp folder. (They should be in the top.)

Under the Build menu, press Build solution and Visual Studio should compile you an executable that is located in C:\dcplusplus\dcplusplus696\app\.

To change Python path, go to client->Header Files->StringDefs.h->Properties->Custom build step and change the appropriate values.

SETTING the settings

So you’ve gotten bored and you started looking in StringDefs.h. You notice that there’s a bunch of SETTING_SOME_OBSCURE_OPTION. When you search for it in other places in the source, you end up in resource.h and SomePage.cpp (and of course StringDefs.h) (where ‘SomePage’ is the name of one of the settings pages).

“How can these options then be used elsewhere if there’s no code to back it up? So DC++ completely ignores every single option there is?”
No, DC++ doesn’t. You see, all of the things in StringDefs.h that have SETTINGS_ before it are captions (text) in the settings pages. Meaning, they aren’t used as options. The names of the settings are instead SOME_OBSCURE_OPTION, and if you search for that, I assure you that you will see more places than above files. (And you can call the option with SETTING(SOME_OBSCURE_OPTION) or BOOLSETTING(SOME_OBSCURE_OPTION).)

SCH proudly presents $Search

Ah, yes, today is a “why the NMDC protocol suck and ADC is so great”-post. And today’s protocol bit is brought to you by $Search (paid and sponsored by SCH in ADC) and the file types used. (You should have a look at the Search types post I made a while ago.)

Now, on to the (NMDC) protocol bit. All of the search types are “hard coded” into the protocol, meaning you will need to upgrade other clients to respond to your file type searches. This is unfortunately not enough of the NMDC silliness. When you pick a certain file type in DC++, DC++ will change the caption of your choice (“Audio” eg) and to a number. This number is predefined (as the wiki post says) and cannot be changed (because otherwise, you’d receive wrong search results or not get any – depending on what you change the number to). This basically means that you cannot tell DC++ (code wise, considering there is no way to do it in the GUI) to “search for _filename_ but only include audio extension AND video extension”. This is because there is no way to combine the different numbers. Now you’re thinking “but can’t you add them and the send that number out?”, and sure, you can do that. But you won’t get the result your after. Eg, “Audio” is 2 and “Compressed files” is 3. Now, if you add these, they (of course) become 5. Now, the problem is that 5 is “Executables”, making all of the other clients think you’re after “executables” and not “audio” and “compressed files”.

“Sigh… Every time you talk about NMDC, I hear something bad… Fine. So, what’s so good with ADC then?”

Ah, my dearest Watson, it is very simple. In ADC’s SCH, one can specify a “EX” (“extension”)Â when searching, and the responding client have to match files with at least one of those EXs. This means that we can specify completely what kind of file types we want – even if the other client hasn’t hard coded any file extensions in its client).

Me, myself and Unsigned

One of the problems when creating software is to predict and know what kind of input people will give when they fiddle around in the settings of the program. DC++ no less also has this issue. Though, while it’s easy to picture (as a programmer) what the user input will be, the code outcome might not always be what the programmer originally intended.

The issue I’m going to talk about today is an issue that arose with people upgrading from DC++ 0.674 to 0.691. (I don’t know if the problem was or not possible with 0.674.)

A bug report and patch was swiftly created and will most likely be introduced in “0.692” (upcoming version).

If you look at the patch, you will see that lines starting with ‘-‘ is removed and ‘+’ is added. With this knowledge, the only “real” change you will see in the patch is that instead of “short” it says “unsigned short”. What this change really does lies in the way C++ (DC++ is written in C++) is designed.
(If you have programming knowledge, you know a short is a type for variables/functions etc. For the no-programming-knowledge-people; Consider that you have a box. This box can store a value, but only one, at any given time. Now, this box have to have a ‘type’, meaning it can only contain values of that certain type. short is one of those types.)

In C++, if a type has nothing before it, it is ‘signed’; This means that it can contain values up to 2^15. The problem is that socket ports can reach 2^16. And this is where the ‘unsigned’ comes in the picture. If a type has ‘unsigned’ before, it not only support 2^15, but also 2^16. We come to the conclusion that using ‘unsigned’ before removes our issue.

Another thing you might notice with the current behaviour, it is that if you input a value above 2^15 (but below 2^16), you will then use – 2^16, this of course leading to a negative value. An interesting thing is that if you input something above 2^16, the value used will then also be – 2^16.

Creating a new Settings page

Creating a new Settings page

Here you go. A nice ‘tutorial’ on creating new Settings pages. I know I’ve removed the help file bit, but it isn’t neccesary. (I know, the formatting is terrible, but I don’t feel like fixing it.)

 

1) Include the header file to PropertiesDlg.cpp

#include “NewPage.h”

 

2) In the same file, in PropertiesDlg::PropertiesDlg(HWND parent, …) { }, add:

pages[n++] = new NewPage(s);

 

3) In PropertiesDlg.h, change the number on this line:

enum { numPages = 14 };

Just change the number to how many Settings-pages you have.

4) In DCPlusPlus.vcproj, add these lines:

<File
RelativePath=”.\windows\NewPage.cpp”>
</File>
<File
RelativePath=”.\windows\NewPage.h”>
</File>

 

5) In the NewPage.cpp, add at the top:
#include “stdafx.h”
#include “../client/DCPlusPlus.h”
#include “Resource.h”

#include “NewPage.h”
#include “CommandDlg.h”

#include “../client/SettingsManager.h”

6) Add:
LRESULT NewPage::onInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
{
PropPage::translate((HWND)(*this), texts); // ‘texts’ here is a static TextItem array. Omit if desired.
PropPage::read((HWND)*this, items, 0, 0); // ‘items’ here is a static Item array. Omit if desired.

// Do specialized reading here
return TRUE;
}

7) Add:
void NewPage::write() {
PropPage::write((HWND)*this, items, 0, 0); // ‘items’ here is a static Item array, the very same variable as on 6). Omit if desired.
}

8.1) If you want to have text in your page, add:
PropPage::TextItem NewPage::texts[] = {
{ IDC_SETTINGS_SOME_SETTING, ResourceManager::SOME_TEXT },
{ IDC_SETTINGS_ANOTHER_SETTING, ResourceManager::ANOTHER_TEXT },
{ 0, ResourceManager::SETTINGS_AUTO_AWAY } // Pretty much used everywhere else… You can might aswell include it.
};
Remember that you have to have the ‘texts’ array included.

8.2) If you want to have items in your page, add:
PropPage::Item NewPage::items[] = {
{ IDC_SOME_ITEM, SettingsManager::SOME_TEXT_BLAH, PropPage::T_INT },
{ IDC_ANOTHERITEM, SettingsManager::ANOTHER_TEXT_BLAH, PropPage::T_STRING },
{ 0, 0, PropPage::T_END }
};
Depending on the item, use T_INT or T_STRING.

Well, you get the hang of it there.

9) In NewPage.h, add:
#ifndef NEWPAGE_H
#define NEWPAGE_H

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#include <atlcrack.h>
#include “PropPage.h”
#include “ExListViewCtrl.h”

class NewPage : public CPropertyPage<IDD_NEWPAGE>, public PropPage
{
public:
NewPage(SettingsManager *s) : PropPage(s) {
SetTitle(CTSTRING(SETTINGS_NEWPAGE));
m_psp.dwFlags |= PSP_HASHELP;
};

virtual ~NewPage() {
};

BEGIN_MSG_MAP(NewPage)
MESSAGE_HANDLER(WM_INITDIALOG, onInitDialog)
END_MSG_MAP()

LRESULT onInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/);

// Common PropPage interface
PROPSHEETPAGE *getPSP() { return (PROPSHEETPAGE *)*this; }
virtual void write();

protected:

static Item items[]; // If you want it that is…
static TextItem texts[]; // If you want it that is…
};

#endif //NEWPAGE_H

10) Last, you need to add it to resource.h:

#define IDD_NEWPAGE 123
11) Add SETTING_NEWPAGE to StringDefs.h.
Design a site like this with WordPress.com
Get started