Workarounds for various problems

One of the special joys of working with Windows is the never-ending challenge of discovering and working around ratty bugs in crummy drivers. With Windows late to arrive with a resounding thud in the worlds of networking and multimedia, Speak Freely finds itself close to the frontier, as it were, where frequent raids by marauding bands of byte bandits are the price one pays for the privilege of pioneering. The defensive programmer finds himself transcending that time-proven style of software development and becoming truly paranoid, always looking over his shoulder for the next incoming arrow of misfortune. This is, after all, a system on which functions such as GetTextMetrics() can return an error status.

The Options/Workarounds menu tree allows you to select workarounds for various errors in audio and network drivers. In an ideal world none of these would be needed, but in an ideal world Windows wouldn't exist. All workaround settings are remembered from session to session. Workarounds can be selected only when no connections are active, and some workarounds take effect only when Speak Freely is restarted; a message box will appear to let you know if this is the case.

Available workarounds are described in the following paragraphs, along with suggestions as to when enabling them may be necessary.

Audio

Assume Half-duplex
Assumes the sound card is half-duplex without requiring it to fail an output open while input is open. Accommodates cards which are actually half-duplex but don't indicate so by failing when one attempts to open input and output simultaneously. Also handles cards which crash the system or application when you try to open them in full-duplex mode.

Assume 11025 Samples/sec
Assumes the card is capable only of 11025 samples per second mode, not our preferred 8000 samples per second. Permits correct operation on cards which don't fail when opened with a sample rate of 8000 samples per second but which can't actually run at that rate.

Set Maximum Volume on Ring
If this item is checked, when the first packet of a remote ring request is received, the output volume is set (if the sound card has that capability) to maximum. If other programs on your machine mute the speaker or turn down the volume to a low level, enabling this item may keep you from missing a call. But beware: some sound cards don't correctly handle setting the output volume--I've even encountered one which mutes the microphone when output volume is changed! So if you enable this mode, be sure to run some tests to make sure it's behaving as intended on your machine.

Disable Adaptive Output Rate Adjustment
When playing audio received from other sites, Speak Freely normally monitors the rate at which your machine plays the audio and, if necessary, speeds up audio output to avoid falling behind the rate at which audio is arriving. This avoids the problem of long delays when connected to a site which is transmitting continuously (broadcasting or sending in full-duplex mode) with audio hardware with a sample rate faster than your own. Rate adjustment is performed only when necessary and, while it speeds up the audio and shifts the pitch toward the treble, these effects are rarely noticeable. If you find the effects of output rate adjustment disagreeable and would rather put up with potential lag between when audio is sent and when you hear it, check this item to disable rate adjustment.

Network

Always Bind Socket
When a network socket is created for transmitting sound, there's no reason to bind it to an address, but some network drivers are reputed to fail if a socket isn't bound. Checking this menu item binds transmit sockets to persuade such feeble minded networks to let us use them.

Never Connect Outbound Socket
Don't connect() the output sockets. This implies we'll always use sendto() to write to those sockets. Clears "Use send(), Not sendto()" mode if set. Some WINSOCK implementations, notably Microsoft's own in Windows NT and Windows 95, blatantly diverge from the Berkeley sockets practice of treating connect() on a datagram socket as merely specifying a default address, not prohibiting subsequent use of sendto() with an explicit address. Checking this item disables the call on connect() entirely, just in case there's some driver which becomes entirely befuddled if it is used.

Use send(), Not sendto()
Always use send() to write to outbound sockets; don't wait for a sendto() to fail first. Accommodates drivers where a sendto() on a connected socket crashes the application or system. Clears "Never Connect Outbound Socket" mode if set. We normally auto-detect the failure of sendto() on a connected socket and fall back to send(). This item allows entirely bypassing the sendto() just in case it wreaks havoc when used on a connected socket.

Multicast TTL Argument Is char
The arguments for the multicast setsockopt() calls IP_MULTICAST_TTL and IP_MULTICAST_LOOP are documented as type char in every Unix Socket implementation I've seen. The Windows Socket 1.1 specification does not contain these calls, as multicast was not a part of WINSOCK at the time. Microsoft's application note on multicast support in Windows NT (and now Windows 95) shows the argument for these two calls as int and, sure enough, if you pass a char the call errors with WSAEFAULT (bad address). Speak Freely conforms to the Microsoft specification and passes int arguments to these two calls but, just in case there's a more Unix-like WINSOCK out there which requires a char argument, provides you this workaround to use char instead. Even though we're running on a little-endian machine, since the length of the argument is passed in the setsockopt() call, the two cases are distinguishable.

Disable Output Overflow Recovery
Some versions of Winsock appear to crash the machine rather than throwing away UDP packets when the user selects a compression mode which transmits faster than the outbound network connection can accommodate. Speak Freely attempts to detect this and discard packets itself when this situation occurs, since losing data is better than a hung machine. The mechanism used to detect and recover from output overflow ventures into poorly-lit regions of Winsock where I suspect may lurk many bugs in various implementations, given how many of the easy things so many manage to get wrong. This workaround turns off output overflow detection and recovery code for such buggy Winsocks, running the risk of a crash due to output overflow if they are also buggy in that regard.

Disable Message Loop Insurance
If the selected compression and encryption modes (or the modes in packets being received) exceed the ability of the CPU to process in real time, there's a risk Speak Freely will hang Windows since sound buffers or packets from the network, combined with the computing to process them, result in Speak Freely never going idle and relinquishing control to other applications. To avoid this, there's a mechanism in Speak Freely which detects if 350 milliseconds or more have elapsed since the last opportunity for other applications to run and, if so, explicitly yields control to any waiting application(s). On slower machines, the very mechanism which saves them from hanging may, itself, cause pauses in sound. So, you can disable the message loop check (restoring the potential for a hang), if necessary, with this workaround. Don't disable it until you're confident your machine is working well with the compression and encryption modes you've settled on.

Get Host Name Synchronously
When you enter a numeric IP address (for example, 127.112.201.14) rather than a host name, Speak Freely attempts to look up the host name to display it in the connection window. It does this the recommended way, with the non-blocking call WSAAsyncGetHostByAddr. Unfortunately, this does not work correctly on every Winsock. The one that comes with Sun Select PC-NFS 5.1, for example, returns the correct results but plants a time bomb that can explode when you finally exit Speak Freely. This workaround uses the blocking call gethostbyaddr() which does not seem to trigger the bomb. Not that it works perfectly--it forgets to null terminate the host string it returns, but that's just ugly, not catastrophic. If the Winsock identifies itself as PC-NFS, this workaround is enabled by default.

Protocol

No Speak Freely Heartbeat
Disable the periodic Speak Freely protocol heartbeat on the control channel. This is primarily intended as a last resort if the (less than 1%) added bandwidth saturates a close to the edge connection, and also in case the control channel packets awake something horrid lurking on the next higher port.

Large RTP Protocol Packets
Uses Speak Freely's preferred packet sizes for GSM and LPC compression rather than those typically sent by RTP programs. Most RTP programs were developed on fast workstations with high bandwidth network connectivity. Speak Freely users generally have slower machines and network links which benefit from larger packets. Try this if the person you're talking to reports halting audio in RTP protocol.

Disable VAT Protocol Detection
VAT protocol will never be automatically selected as a result of receiving a message on the control channel which resembles a VAT control message. Enable this if you never receive VAT protocol messages and are annoyed at how long it takes to identify the protocol of encrypted RTP messages.

Disable RTP Protocol Detection
RTP protocol will never be automatically selected as a result of receiving a message on the control channel which resembles a RTP control message. Enable this if you never receive RTP protocol messages and are annoyed at how long it takes to identify the protocol of encrypted VAT messages.

No Encryption of RTP Control Packets
RTP control packets can, according to the standard, be sent either encrypted or in the clear. Most RTP programs I've encountered encrypt their control packets, so this is the default Speak Freely sends (it accepts both encrypted and clear packets). If you set this workaround, control packets are sent in the clear.