Archive for March, 2010

Small E-mail Servers

I’ve run a small e-mail server at airs.com for many years, providing POP and forwarding services for friends and family. In the early days of the net several people found it useful to have a fixed e-mail address which they could forward to their ISP. Later on commercial services appeared, like pobox.com, and these days there are many options available.

The spam wars have made running a small e-mail server steadily harder. I’ve had to change a number of characteristics about the system over the years. One aspect that is difficult to change is that since the server forwards e-mail, in some cases it forwards spam which get through my own spam blockers. That spam is sometimes picked up by the system to which the e-mail is forwarded. When that happens, my server can be marked as a spam source.

When this has happened in the past, it’s been ISPs marking my server as a spam source, and they’ve always provided a way for me to tell them that my system is OK. This has always worked fine (it does require updating in the rare cases when I change the IP address of the server).

Recently I’ve been seeing something new: spam blocking networks which are shared by various recipient systems. What is interesting here is that these spam blocking networks make at least some of their money by charging people to send e-mail into their network. So, for example, returnpath.net decided to block e-mail from my server. They don’t provide any information about why they’ve done so, which makes it hard for me to fix the problem. I can enter the IP address to temporarily remove my server from their blacklist, which of course I have done. But what they really want to do is charge me $200 to have my server listed as a valid e-mail sender. Shortly after signing up with them for the sole purpose of removing my server from their blacklist, I got an e-mail from one of their sales reps offering to sell me their services to ensure that my e-mail messages got delivered. So far I have declined to pay, and some of my e-mail, e.g., to John Levine’s compilers list, is getting blocked.

In other words, what we have here is a spam blocking network which makes money by charging people to send e-mail messages through their spam blocking services. It’s an interesting little low-key protection racket. They have to keep it low-key, since they have to provide a decent quality spam blocking service; otherwise, people won’t use them and they will have nothing to sell to e-mail senders. They have to limit the spamminess of their customers, since otherwise, again, people won’t use their blacklist and they will have nothing to sell. Unfortunately, small e-mail servers like the one I run are caught in the middle. I can hardly pay off every spam blocking service. I don’t want to have to pay off any of them, merely to run a forwarding service.

I’m sure things will change again, but the current situation is not a very good one.

Comments (13)

High Mimetic

Roger Zelazny, in discussing why he liked to write science fiction, referred to Northrop Frye’s theory of modes. In Zelazny’s interpretation, Frye described characters in fiction in four modes:

  1. The mythic mode is stories about gods.
  2. The high mimetic mode is stories about heroes, people who are better than ordinary humans.
  3. The low mimetic mode is stories about ordinary people.
  4. The ironic mode is stories about people who are worse than ordinary people–criminals, buffoons.

(Frye also talked about a romantic mode but Zelazny doesn’t mention it.)

Zelazny said that he liked science fiction because it let him write literature in the mythic or high mimetic mode. Certainly many of his stories are about gods or people with great powers. Zelazny argued that literature today outside of science fiction is mainly confined to the low mimetic and the ironic mode. There are many superb stories about ordinary people. There are few stories about remarkable people which are not history and are not genre stories like science fiction or romances.

This started me thinking about other areas where stories are told in the high mimetic mode. Superhero comics are obviously told entirely in that mode. Another place we see it is a certain set of action movies: James Bond, for example, is a high mimetic mode character. But these stories, while enjoyable, rarely rise to the level of good literature.

An exception is The Hurt Locker. This excellent movie, which well deserved the Oscars it just won, is a straight-up action movie. It passed one of the acid tests of the action movie: I saw it twice, and I didn’t see anything the second time around that I missed the first time. With artistic movies I often get a new perspective on a second viewing; with action movies I rarely do. The movie also operates in the high mimetic mode: the protagonist, William James, is a heroic character. He is not a perfect human being, but he is exceptionally capable and brave.

But despite the high mimetic mode character, the movie does not operate as a standard hero’s journey, there is no evil mastermind or any identified antagonist. The movie is simply a collection of relatively unrelated incidents which reveal the characters. James does come to understand himself better during the movie—or, since we really only hear his inner thoughts in one scene, perhaps he understood himself all along. The combination of literary techniques with high mimetic mode make this a genuinely exceptional movie.

Zelazny, of course, used the same approach throughout his career, with varying degrees of success.

Comments

Signed or Unsigned

C has always permitted comparisons between any integer type, and C++ follows its lead. Comparing signed types to signed types is straightforward: you sign extend the smaller type. Likewise, when comparing unsigned types to unsigned types, you zero extend. When comparing signed and unsigned types, the rules are less clear.

The C standard specifies a type ordering: long long > long > int > short > char. If the unsigned type appears in that ordering before the signed type, then the signed value is converted to the unsigned type. Note that this happens even if the types are the same size (e.g., either long long and long or long and int are often the same size). Otherwise, if the signed type is larger than the unsigned type, in the sense of having more bits, then the unsigned value is converted to the signed type. Otherwise both values are converted to the unsigned type which corresponds to the signed type.

Pre-standard K&R C used a different rule, but that is old enough now that we no longer have to worry about it.

What this rule means is that if you write portable code, such that you don’t know the sizes of types, you can not predict whether the comparison will be done as a signed comparison or an unsigned comparison. Therefore, the gcc compiler has an option -Wsign-compare. However, this option is sufficiently awkward to avoid that it is not part of -Wall, though it is part of -Wextra (the difference between -Wall and -Wextra is that the former gives warnings for which false positives are easy to avoid through simple code changes; the latter gives warnings which are generally useful but for which false positives are harder to avoid).

There are good reasons to use signed types: they don’t have odd behaviour around zero, so you can write i < limit - 1 without worrying about the case limit == 0. There are good reasons to use unsigned types for things like the number of elements in a container: you get the full range of sizes, rather than limiting yourself to only the positive half. In particular, the C++ standard containers use unsigned types as their size. Combining these two rules gets you in trouble with portable code. The only reasonable answer I can see for portable code is to use -Wsign-compare and work around the many false positive warnings.

Go avoids these problems in two ways. First, there are no implicit conversions, so you can never be surprised by having a comparison become unsigned when you expected signed. You have to explicitly say which type of conversion you mean. Second, Go intentionally discards half of memory, and takes the philosophy that if you want a container which can hold more values than fit in a signed int, you should write a special purpose large container.

Comments (2)