Download

Install

Unpack GPRSD.EXE into some directory.
Add a gprs.ini (rename one of the two sample files and edit).
You may need the default simple.inf if that's what you decide
to use for your serial modem.

With a modem that uses the Windows "unimodem" driver
on top of an opaque serial port, either use the
included simple.inf, or provide your own INF file.
In such cases, it's better NOT to have a modem
"driver" installed. Gprsd will install it for you.

For USB GPRS/3G/4G modems that still have an AT command
interface and PPP, note that the COM port is a "side effect",
just one of several interfaces presented by the USB device driver.
For USB modems, the responsibility is yours, to install
the USB modem driver in the usual way (provide a driver
to Windows when they ask for one) and gprsd.exe will try
to make use of it.
For USB modems, gprsd.exe doesn't even need an INF file.
But, you definitely need a custom gprs.ini,
where you enter your modem's COM port and a USB device ID string.

In general, just run GPRSD.EXE - it will check what's
in the system, possibly install its own modem INF file,
and create an RAS connection profile ("phonebook entry").

For repeated deployments, you will want to provide your own
gprs.ini. If you don't have one, just run gprsd.exe
- it will create a default INI file, which you can modify.
Note that there are two sample gprs.ini files included
in the distribution ZIP file.

What it does

The classic GPRS modems speak PPP (emulated locally by the modem)
to their local DTE = host computer. The PPP is handled by the
standard Windows NT+ Remote Access Service (RAS). What RAS cannot do
is keep an eye on the GPRS uplink and redial if necessary.
RAS alone also isn't very good at inserting a SIM PIN,
and generally the Windows modem framework doesn't understand GPRS
extensions to the common Hayes-compatible AT command set.
Hence the inspiration for an additional GPRS-aware dialer
/ connection manager / whatever.

GPRSD does the following:

checks for a COM port

installs a GPRS modem (via an INF file) if missing

patches an AT+CGDCONT=1,"IP","your.apn.name" into the INF file
(for serial modems) or straight into the registry (for USB modems)

creates a "phonebook entry" = RAS "connection" if missing

checks for a modem on the COM port and inits the modem (SIM PIN),
by direct access to COM port (= before RAS is asked to dial out)

dials the phonebook entry = opens a RAS session

keeps pinging a configured target host.
When severeal pings get lost, it hangs up the RAS session
and tries to reconnect, starting from the modem init (point 5. above).

See the source code for ugly details.

Configuration - GPRS.INI

On the first run, GPRSD.EXE creates an INI file with some defaults.
You can modify the values in this file and copy it to other machines
(you need not generate this file on each and every machine.) Configurable
options follow:

COM_PORT=string
default: COM1

MODEM_HWID=string
For serial modems, this can be pretty much anything.
The "simple.inf" uses the string "Maestro".
default: Maestro
For USB modems, you need to enter you modem's USB ID string.
See the sample gprs.ini.usb for an inspiration - you need
to find a similar string in the INF file of your modem
or in the "device properties" of the USB device ("hardware ID's").

MODEM=string
Modem entry in the Windows device management.
The simple.inf conains just "Maestro".
default: Maestro
USB modems have their own respective names.
See the control panel "Modems" for a list
of what you have in the system.

INF_FILE=string
Points to the modem "driver" (INF file).
default: simple.inf
gprsd.exe actually doesn't need an INF file for USB modems.
(You just need to provide the USB ID string, which happens to be
mentioned in a compatible INF file.)

PHONEBOOK_ENTRY=string
default: GPRS

PIN=string
SIM pin, only used if the modem asks for it

APN=string
APN name. Even "public internet access" uses some APN name,
such as "internet.t-mobile.cz". Note that this is not (necessarily)
a DNS name, it's just an APN name string chosen by the GPRS operator.

AUTH=string
default: ANY
possible values: PAP, CHAP, MSCHAP, MSCHAP2 and more...
Authentication mechanism. Some APN setups need e.g. PAP to work correctly
against the remote auth back-end configured at the GGSN. APN auth can be
delegated to customer-side radius servers or some such.
Note: it seems that the XP SP3 RAS API is broken, in that it cannot be
forced to programmatically configure the set of auth protocols desired.
GPRSD.EXE tries to provide the respective set of RASEO_requireXYZ
flags OR'ed together in dwfOptions, OR'ed with RASEO_Custom,
but the phonebook entry ends up using just the "typical"
security settings. It's a bug in RasSetEntryProperties() or what.
= if necessary, you need to edit the phonebook entry created by gprsd.exe
by hand in the "connection properties" - that way your options will stick.

GPRS_NUM=string
The "phone number" to dial out, in order to get the GPRS service.
default: *99***1#
Note that the "1" before the hash character refers to CGDCONT profile number 1.
There can be several AT+CGDCONT profiles (APN names) stored in the modem,
and you can refer to them by the trailing digit in the "GPRS phone number"...

GPRS_USERNAME=string
Leave empty if unused

GPRS_PASSWORD=string
Leave empty if unused

PING_HOSTNAME=string
A DNS name or an IP address of the required Ping target machine
default: www.google.com

PING_TIMEOUT=number in seconds
How long to wait for a response to each PING request (ICMP echo request).
default: 5

PING_RETRIES=number
How many failed pings must fail in a row to initiate a redial.
default: 5

PING_OK_PERIOD=number in seconds
When a ping response arrived just fine, how long to sleep before
sending another PING request. The default is somewhat long,
to avoid incredible volume-based fees to the GPRS operator.
default: 300

PING_RETRY_PERIOD=number in seconds
When a ping timed out, how long to sleep before
sending another PING request. It might look like a good
idea to check again relatively soon. Beware, you may want to
set this longer - to avoid large fees when it's not the
local last mile radio segment that went wrong...
default: 5

RAS_REDIAL_PERIOD=number in seconds
When Ping signals connection down, GPRSD tries to redial immediately.
If this immediate redial fails, the next attempt (and any further
attempts until success) will be preceded by a configurable delay.
This delay should give the modem / GSM network / local PPP stack
some time to recover from an error - and should also limit the
size of an error log file, if you're trying to capture what's going on.
default: 30

SLEEP_ON_MODEM_INIT_FAILURE=number in seconds
When GPRSD fails to init the modem (no response to AT,
modem responds ERROR to AT or some such), GPRSD will try
again with a configurable delay. This should limit the size
of a log file, if you're trying to capture what's going on.
default: 20

Requirements

Windows XP 32bit (not tested on other versions).
Wavecom/Sierra based GPRS modem (or something compatible).
Or maybe pretty much any USB WWAN modem.
The program was tested against Wavecom-based modems sold by
Maestro Wireless / Fargo Telecom (of TW)
and against a Quectel MiniPCI-e 4G modem.

Disclaimer

This software is provided as is. I disclaim any responsibility.
Use at your own risk.

Beware: GPRSD uses Ping (ICMP echo + echo reply messages) to keep
an eye on your GPRS uplink connectivity. This implies data being
transferred, which in turn implies more money charged by the GPRS operator.
There's no way around this - you need to transfer data to check
the status of your GPRS session, and you'll pay for that.
How much, that depends on your negotiated fees.
The PING repetition rate is configurable - you'll find yourself
trading off monitoring precision (in time) vs. volume-based fees.

Further background info

Written in MinGW for Win32. The source code should be reasonably portable
to other compilers.

Known downsides: it's a fairly crude console app. It doesn't have proper
GUI behavior, cannot hide in systray, doesn't alone run as a service
(you may try running it via NSSM). It sends progress messages to its stdout
- to capture that to a file, just use the > sign.
Or download some "tee" variant for Win32, if you want to have a logfile AND
see the output in the console window at the same time.

The reconnect is a mess. The RAS can fail to reconnect for no
obvious reason, once or twice (even when the GSM network is there
and antenna is attached) - and the spectrum of errors returned
by RasDial() et al. is staggering. Even the modem can sometimes
respond "ERROR" to plain "AT" for no apparent reason.
It's not quite possible to distinguish fatal vs. temporary errors.
It's also difficult to tell if the blame is with Windows or with
the modem/network or whatever.
Therefore, GPRSD just keeps on trying to reconnect.
You can even remove the SIM from your modem or turn off the modem,
and GPRSD just keeps trying (and resumes successfully as soon
as you power the modem back on or re-insert its SIM card).

GPRSD is fairly crude/clumsy in how it handles the connection
errors and just keeps trying to redial from scratch. This is deliberate.
It would certainly be possible to check for more detailed status flags
in the modem, but that might make GPRSD sensitive to differences
in firmware versions and modem models, which is NOT desired.
Therefore, GPRSD is generic at the cost of being somewhat clumsy.

The source code contains practical examples of how to use C++/WinAPI
to programmatically install and launch GPRS connectivity via an
RS232-attached GPRS modem. It uses the RAS API and the Setup API.
It also demonstrates how to code a simple PING-style program.

Apologies for poor coding style, mixing basic C types with
Win32-style "Hungarian notation" etc. - the program is based
on snippets taken from various sources (see the Credits).
It would sure use some janitoring to get more unified
/ compact / elegant / extensible... I wish I had the time.

GPRS peculiarities

Monitoring GPRS connectivity is not necessarily an obvious task.

PPP (IPCP) does support keepalives, but these are not much practical
use. There's no way to ask the Windows RAS to use them, and even
if there was a way, there's no guarantee that the GPRS modem relays them
to the "PDP context" (GTP) to really check the GPRS "session status".
There are hints in Cisco documentation that GTP can do keepalives,
but it's difficult to say if these can be relied on...

Another option would be, if you're running some application-level TCP session,
to monitor connectivity via TCP "keepalives". A TCP keepalive is a packet
with zero payload, sent merely to request an ACK from the opposite end.
Such a packet gets generated by calling the socket API's send() function,
and providing it with a buffer with zero length = by submitting to TCP
a data chunk with length = 0.
This way, you might combine connectivity monitoring with your payload
traffic. Unfortunately, it seems that the GPRS endpoints (certainly
the GGSN) manipulate the traffic up to the TCP layer in such a way
that TCP ACK's to keepalives are sent, even though the GPRS session
has actually died (the MT is temporarily out of reach or some such).
GPRS simply tries to buffer as much data as possible and hide retransmissions
on the radio segment from TCP/IP. The buffering happens even with PING requests
and responses (fortunately, ICMP echo responses are NOT locally fudged).

There are some flags in the GPRS modem that can be used to check the
status of a GPRS "network registration" and PDP context. Unfortunately,
these are A) unreliable and B) cannot be read by the host computer
when PPP is up and running. The modem would be able to temporarily
break into command mode (using +++) and then resume, but the Windows
RAS is certainly uncapable of that.
Actually USB WWAN modems typically do have an extra AT command interface
(the DM virtual COM port) that responds to AT commands even while
the modem's own virtual COM port is occupied by PPP. This could be
used to watch signal strength at gprsd runtime, maybe even display
some info about the network (transport network flavour, ARFCN
and whatnot. Note that these "engineering mode" commands
are vendor-specific.) Such functionality using a second COM port
is not implemented at the moment. It would take some additional effort.

In the end, your only chance to monitor the real-world status of a GPRS
session is by classic ICMP PING to some outside host that's known to be
available. Either to some server of your own, or to some well-known
internet site. You could also ping your local GGSN (your default gateway)
if your operator allows this - or some IP address further upstream...
or ping multiple addresses and try some "quorum consensus", or try
a traceroute and infer status from its output. Nevertheless,
any more advanced heuristic approach is complex / problematic.
Thus, the GPRSD approaches this in a rather crude way: it pings a single
outside host and redials if that's not available. This can lead to
false detections of "link down", and it cannot distinguish between
a local last-mile outage and other problems further upstream
(which won't get solved by a redial). Well that's life.

Credits

The whole code is heavily inspired by several articles from
the Code Project website.
I've noticed bugs in some of their code samples (or sometimes in
MS Windows API behavior), but thanks god for that website,
and kudos to all the article authors.
The source code contains specific credits where due.