aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--CHANGES.TXT2
-rw-r--r--android/vm/info.c54
-rw-r--r--audio/alsaaudio.c308
-rw-r--r--audio/esdaudio.c15
-rw-r--r--audio/ossaudio.c8
-rw-r--r--audio/sdlaudio.c17
-rw-r--r--framebuffer.c4
-rw-r--r--osdep.h6
-rw-r--r--slirp2/ip.h64
-rw-r--r--slirp2/ip_input.c140
-rw-r--r--slirp2/misc.c30
-rw-r--r--slirp2/slirp.c2
-rw-r--r--slirp2/slirp.h10
-rw-r--r--slirp2/tcp_input.c45
-rw-r--r--slirp2/tcp_subr.c18
-rw-r--r--slirp2/tcp_var.h25
-rw-r--r--slirp2/tcpip.h11
-rw-r--r--slirp2/udp.c5
-rw-r--r--slirp2/udp.h3
19 files changed, 353 insertions, 414 deletions
diff --git a/CHANGES.TXT b/CHANGES.TXT
index 05820d6..5c87780 100644
--- a/CHANGES.TXT
+++ b/CHANGES.TXT
@@ -72,6 +72,8 @@ OTHER:
- The '-skindir <path>' option now requires that you specify a '-skin <name>'
option as well.
+- Better handling of Audio on Linux for the EsounD and Alsa backends
+
==============================================================================
Changes between 1.6 and 1.7
diff --git a/android/vm/info.c b/android/vm/info.c
index a82b60b..93312ac 100644
--- a/android/vm/info.c
+++ b/android/vm/info.c
@@ -1078,20 +1078,24 @@ _getImagePaths(AvmInfo* i, AvmInfoParams* params )
/* check that there is a skin named 'skinName' listed from 'skinDirRoot'
* this returns 1 on success, 0 on failure
- * on success, the 'temp' buffer will get the path of the real skin
- * directory (after alias expansion, if needed)
+ * on success, the 'temp' buffer will get the path containing the real
+ * skin directory (after alias expansion), including the skin name.
*/
static int
_checkSkinDir( char* temp, char* end, const char* skinDirRoot, const char* skinName )
{
DirScanner* scanner;
char *p, *q;
+ int result;
- p = bufprint(temp, end, "%s/skins/%s",
- skinDirRoot, skinName);
+ p = bufprint(temp, end, "%s/skins/%s",
+ skinDirRoot, skinName);
- if (p >= end || !path_exists(temp))
- return -1;
+ DD("probing skin content in %s", temp);
+
+ if (p >= end || !path_exists(temp)) {
+ return 0;
+ }
/* first, is this a normal skin directory ? */
q = bufprint(p, end, "/layout");
@@ -1103,6 +1107,7 @@ _checkSkinDir( char* temp, char* end, const char* skinDirRoot, const char* s
/* second, is it an alias to another skin ? */
*p = 0;
+ result = 0;
scanner = dirScanner_new(temp);
if (scanner != NULL) {
for (;;) {
@@ -1120,13 +1125,14 @@ _checkSkinDir( char* temp, char* end, const char* skinDirRoot, const char* s
q = bufprint(p, end, "/layout");
if (q < end && path_exists(temp)) {
/* yes, it's an alias */
- *p = 0;
- return 1;
+ *p = 0;
+ result = 1;
+ break;
}
}
dirScanner_free(scanner);
}
- return 0;
+ return result;
}
static int
@@ -1159,9 +1165,14 @@ _getSkin( AvmInfo* i, AvmInfoParams* params )
* user wants, unless an explicit name was given
*/
if (!explicitSkin) {
- p = bufprint(temp, end, "%s/skin/layout", i->contentPath);
- if (p < end && path_exists(temp)) {
+ char* q;
+
+ p = bufprint(temp, end, "%s/skin", i->contentPath);
+ q = bufprint(p, end, "/layout");
+ if (q < end && path_exists(temp)) {
/* use this one - cheat a little */
+ *p = 0;
+ D("using skin content from %s", temp);
qemu_free(i->skinName);
i->skinName = qemu_strdup("skin");
i->skinDirPath = qemu_strdup(i->contentPath);
@@ -1190,6 +1201,19 @@ _getSkin( AvmInfo* i, AvmInfoParams* params )
} while (0);
+ /* separate skin name from parent directory. the skin name
+ * returned in 'temp' might be different from the original
+ * one due to alias expansion so strip it.
+ */
+ p = strrchr(temp, '/');
+ if (p == NULL) {
+ /* should not happen */
+ DD("weird skin path: %s", temp);
+ return -1;
+ }
+
+ *p = 0;
+ DD("found skin content in %s", temp);
i->skinDirPath = qemu_strdup(temp);
return 0;
}
@@ -1413,14 +1437,12 @@ _getBuildSkin( AvmInfo* i, AvmInfoParams* params )
p = bufprint( temp, end, "%s", skinDir );
}
- q = bufprint(p, end, "/%s/layout", skinName);
+ q = bufprint(p, end, "/%s/layout", skinName);
if (q >= end || !path_exists(temp)) {
+ DD("skin content directory does not exist: %s", temp);
if (skinDir)
dwarning("could not find valid skin '%s' in %s:\n",
- skinName, skinDir);
- else
- DD("could not find directory for skin '%s'",
- skinName);
+ skinName, temp);
return -1;
}
*p = 0;
diff --git a/audio/alsaaudio.c b/audio/alsaaudio.c
index 21aae59..cc43841 100644
--- a/audio/alsaaudio.c
+++ b/audio/alsaaudio.c
@@ -80,6 +80,9 @@
DYNLINK_FUNC(const char*,snd_strerror,(int errnum)) \
DYNLINK_FUNC(int,snd_pcm_open,(snd_pcm_t **pcm, const char *name,snd_pcm_stream_t stream, int mode)) \
DYNLINK_FUNC(int,snd_pcm_close,(snd_pcm_t *pcm)) \
+ DYNLINK_FUNC(int,snd_pcm_hw_params_set_buffer_size_near,(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, snd_pcm_uframes_t *val)) \
+ DYNLINK_FUNC(int,snd_pcm_hw_params_set_period_size_near,(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, snd_pcm_uframes_t *val, int *dir)) \
+ DYNLINK_FUNC(int,snd_pcm_hw_params_get_format,(const snd_pcm_hw_params_t *params, snd_pcm_format_t *val)) \
#define DYNLINK_FUNCTIONS_INIT \
alsa_dynlink_init
@@ -118,44 +121,24 @@ static struct {
unsigned int period_size_out;
unsigned int threshold;
- int buffer_size_in_overriden;
- int period_size_in_overriden;
+ int buffer_size_in_overridden;
+ int period_size_in_overridden;
- int buffer_size_out_overriden;
- int period_size_out_overriden;
+ int buffer_size_out_overridden;
+ int period_size_out_overridden;
int verbose;
} conf = {
-#ifdef HIGH_LATENCY
- .size_in_usec_in = 1,
- .size_in_usec_out = 1,
-#endif
+ .buffer_size_out = 1024,
.pcm_name_out = "default",
.pcm_name_in = "default",
-#ifdef HIGH_LATENCY
- .buffer_size_in = 400000,
- .period_size_in = 400000 / 4,
- .buffer_size_out = 400000,
- .period_size_out = 400000 / 4,
-#else
-#define DEFAULT_BUFFER_SIZE 1024
-#define DEFAULT_PERIOD_SIZE 256
- .buffer_size_in = DEFAULT_BUFFER_SIZE * 4,
- .period_size_in = DEFAULT_PERIOD_SIZE * 4,
- .buffer_size_out = DEFAULT_BUFFER_SIZE,
- .period_size_out = DEFAULT_PERIOD_SIZE,
- .buffer_size_in_overriden = 0,
- .buffer_size_out_overriden = 0,
- .period_size_in_overriden = 0,
- .period_size_out_overriden = 0,
-#endif
- .threshold = 0,
- .verbose = 0
};
struct alsa_params_req {
int freq;
- audfmt_e fmt;
+ snd_pcm_format_t fmt;
int nchannels;
+ int size_in_usec;
+ int override_mask;
unsigned int buffer_size;
unsigned int period_size;
};
@@ -163,6 +146,7 @@ struct alsa_params_req {
struct alsa_params_obt {
int freq;
audfmt_e fmt;
+ int endianness;
int nchannels;
snd_pcm_uframes_t samples;
};
@@ -234,7 +218,8 @@ static int aud_to_alsafmt (audfmt_e fmt)
}
}
-static int alsa_to_audfmt (int alsafmt, audfmt_e *fmt, int *endianness)
+static int alsa_to_audfmt (snd_pcm_format_t alsafmt, audfmt_e *fmt,
+ int *endianness)
{
switch (alsafmt) {
case SND_PCM_FORMAT_S8:
@@ -275,7 +260,6 @@ static int alsa_to_audfmt (int alsafmt, audfmt_e *fmt, int *endianness)
return 0;
}
-#if defined DEBUG_MISMATCHES || defined DEBUG
static void alsa_dump_info (struct alsa_params_req *req,
struct alsa_params_obt *obt)
{
@@ -289,7 +273,6 @@ static void alsa_dump_info (struct alsa_params_req *req,
req->buffer_size, req->period_size);
dolog ("obtained: samples %ld\n", obt->samples);
}
-#endif
static void alsa_set_threshold (snd_pcm_t *handle, snd_pcm_uframes_t threshold)
{
@@ -326,16 +309,17 @@ static int alsa_open (int in, struct alsa_params_req *req,
{
snd_pcm_t *handle;
snd_pcm_hw_params_t *hw_params;
- int err, freq, nchannels;
+ int err;
+ int size_in_usec;
+ unsigned int freq, nchannels;
const char *pcm_name = in ? conf.pcm_name_in : conf.pcm_name_out;
- unsigned int period_size, buffer_size;
snd_pcm_uframes_t obt_buffer_size;
const char *typ = in ? "ADC" : "DAC";
+ snd_pcm_format_t obtfmt;
freq = req->freq;
- period_size = req->period_size;
- buffer_size = req->buffer_size;
nchannels = req->nchannels;
+ size_in_usec = req->size_in_usec;
FF_snd_pcm_hw_params_alloca (&hw_params);
@@ -367,12 +351,12 @@ static int alsa_open (int in, struct alsa_params_req *req,
}
err = FF(snd_pcm_hw_params_set_format) (handle, hw_params, req->fmt);
- if (err < 0) {
+ if (err < 0 && conf.verbose) {
alsa_logerr2 (err, typ, "Failed to set format %d\n", req->fmt);
goto err;
}
- err = FF(snd_pcm_hw_params_set_rate_near) (handle, hw_params, (unsigned*)&freq, 0);
+ err = FF(snd_pcm_hw_params_set_rate_near) (handle, hw_params, &freq, 0);
if (err < 0) {
alsa_logerr2 (err, typ, "Failed to set frequency %d\n", req->freq);
goto err;
@@ -381,7 +365,7 @@ static int alsa_open (int in, struct alsa_params_req *req,
err = FF(snd_pcm_hw_params_set_channels_near) (
handle,
hw_params,
- (unsigned*)&nchannels
+ &nchannels
);
if (err < 0) {
alsa_logerr2 (err, typ, "Failed to set number of channels %d\n",
@@ -396,130 +380,79 @@ static int alsa_open (int in, struct alsa_params_req *req,
goto err;
}
- if (!((in && conf.size_in_usec_in) || (!in && conf.size_in_usec_out))) {
- if (!buffer_size) {
- buffer_size = DEFAULT_BUFFER_SIZE;
- period_size= DEFAULT_PERIOD_SIZE;
- }
- }
+ if (req->buffer_size) {
+ unsigned long obt;
- if (buffer_size) {
- if ((in && conf.size_in_usec_in) || (!in && conf.size_in_usec_out)) {
- if (period_size) {
- err = FF(snd_pcm_hw_params_set_period_time_near) (
- handle,
- hw_params,
- &period_size,
- 0
- );
- if (err < 0) {
- alsa_logerr2 (err, typ,
- "Failed to set period time %d\n",
- req->period_size);
- goto err;
- }
- }
+ if (size_in_usec) {
+ int dir = 0;
+ unsigned int btime = req->buffer_size;
err = FF(snd_pcm_hw_params_set_buffer_time_near) (
handle,
hw_params,
- &buffer_size,
- 0
+ &btime,
+ &dir
);
-
- if (err < 0) {
- alsa_logerr2 (err, typ,
- "Failed to set buffer time %d\n",
- req->buffer_size);
- goto err;
- }
+ obt = btime;
}
else {
- int dir;
- snd_pcm_uframes_t minval;
-
- if (period_size) {
- minval = period_size;
- dir = 0;
-
- err = FF(snd_pcm_hw_params_get_period_size_min) (
- hw_params,
- &minval,
- &dir
- );
- if (err < 0) {
- alsa_logerr (
- err,
- "Could not get minmal period size for %s\n",
- typ
- );
- }
- else {
- if (period_size < minval) {
- if ((in && conf.period_size_in_overriden)
- || (!in && conf.period_size_out_overriden)) {
- dolog ("%s period size(%d) is less "
- "than minmal period size(%ld)\n",
- typ,
- period_size,
- minval);
- }
- period_size = minval;
- }
- }
+ snd_pcm_uframes_t bsize = req->buffer_size;
- err = FF(snd_pcm_hw_params_set_period_size) (
- handle,
- hw_params,
- period_size,
- 0
- );
- if (err < 0) {
- alsa_logerr2 (err, typ, "Failed to set period size %d\n",
- req->period_size);
- goto err;
- }
- }
+ err = FF(snd_pcm_hw_params_set_buffer_size_near) (
+ handle,
+ hw_params,
+ &bsize
+ );
+ obt = bsize;
+ }
+ if (err < 0) {
+ alsa_logerr2 (err, typ, "Failed to set buffer %s to %d\n",
+ size_in_usec ? "time" : "size", req->buffer_size);
+ goto err;
+ }
- minval = buffer_size;
- err = FF(snd_pcm_hw_params_get_buffer_size_min) (
+ if ((req->override_mask & 2) && (obt - req->buffer_size))
+ dolog ("Requested buffer %s %u was rejected, using %lu\n",
+ size_in_usec ? "time" : "size", req->buffer_size, obt);
+ }
+
+ if (req->period_size) {
+ unsigned long obt;
+
+ if (size_in_usec) {
+ int dir = 0;
+ unsigned int ptime = req->period_size;
+
+ err = FF(snd_pcm_hw_params_set_period_time_near) (
+ handle,
hw_params,
- &minval
+ &ptime,
+ &dir
);
- if (err < 0) {
- alsa_logerr (err, "Could not get minmal buffer size for %s\n",
- typ);
- }
- else {
- if (buffer_size < minval) {
- if ((in && conf.buffer_size_in_overriden)
- || (!in && conf.buffer_size_out_overriden)) {
- dolog (
- "%s buffer size(%d) is less "
- "than minimal buffer size(%ld)\n",
- typ,
- buffer_size,
- minval
- );
- }
- buffer_size = minval;
- }
- }
+ obt = ptime;
+ }
+ else {
+ int dir = 0;
+ snd_pcm_uframes_t psize = req->period_size;
- err = FF(snd_pcm_hw_params_set_buffer_size) (
+ err = FF(snd_pcm_hw_params_set_period_size_near) (
handle,
hw_params,
- buffer_size
+ &psize,
+ &dir
);
- if (err < 0) {
- alsa_logerr2 (err, typ, "Failed to set buffer size %d\n",
- req->buffer_size);
- goto err;
- }
+ obt = psize;
}
- }
- else {
- dolog ("warning: Buffer size is not set\n");
+
+ if (err < 0) {
+ alsa_logerr2 (err, typ, "Failed to set period %s to %d\n",
+ size_in_usec ? "time" : "size", req->period_size);
+ goto err;
+ }
+
+ if ((req->override_mask & 1) && (obt - req->period_size))
+ dolog ("Requested period %s %u was rejected, using %lu\n",
+ size_in_usec ? "time" : "size", req->period_size, obt);
}
err = FF(snd_pcm_hw_params) (handle, hw_params);
@@ -534,6 +467,17 @@ static int alsa_open (int in, struct alsa_params_req *req,
goto err;
}
+ err = FF(snd_pcm_hw_params_get_format)(hw_params, &obtfmt);
+ if (err < 0) {
+ alsa_logerr2 (err, typ, "Failed to get format\n");
+ goto err;
+ }
+
+ if (alsa_to_audfmt (obtfmt, &obt->fmt, &obt->endianness)) {
+ dolog ("Invalid format was returned %d\n", obtfmt);
+ goto err;
+ }
+
err = FF(snd_pcm_prepare) (handle);
if (err < 0) {
alsa_logerr2 (err, typ, "Could not prepare handle %p\n", handle);
@@ -544,28 +488,36 @@ static int alsa_open (int in, struct alsa_params_req *req,
snd_pcm_uframes_t threshold;
int bytes_per_sec;
- bytes_per_sec = freq
- << (nchannels == 2)
- << (req->fmt == AUD_FMT_S16 || req->fmt == AUD_FMT_U16);
+ bytes_per_sec = freq << (nchannels == 2);
+
+ switch (obt->fmt) {
+ case AUD_FMT_S8:
+ case AUD_FMT_U8:
+ break;
+
+ case AUD_FMT_S16:
+ case AUD_FMT_U16:
+ bytes_per_sec <<= 1;
+ break;
+ }
threshold = (conf.threshold * bytes_per_sec) / 1000;
alsa_set_threshold (handle, threshold);
}
- obt->fmt = req->fmt;
obt->nchannels = nchannels;
obt->freq = freq;
obt->samples = obt_buffer_size;
+
*handlep = handle;
-#if defined DEBUG_MISMATCHES || defined DEBUG
- if (obt->fmt != req->fmt ||
- obt->nchannels != req->nchannels ||
- obt->freq != req->freq) {
- dolog ("Audio paramters mismatch for %s\n", typ);
+ if (conf.verbose &&
+ (obt->fmt != req->fmt ||
+ obt->nchannels != req->nchannels ||
+ obt->freq != req->freq)) {
+ dolog ("Audio paramters for %s\n", typ);
alsa_dump_info (req, obt);
}
-#endif
#ifdef DEBUG
alsa_dump_info (req, obt);
@@ -705,11 +657,9 @@ static int alsa_init_out (HWVoiceOut *hw, audsettings_t *as)
ALSAVoiceOut *alsa = (ALSAVoiceOut *) hw;
struct alsa_params_req req;
struct alsa_params_obt obt;
- audfmt_e effective_fmt;
- int endianness;
- int err, result = -1;
snd_pcm_t *handle;
audsettings_t obt_as;
+ int result = -1;
/* shut alsa debug spew */
if (!D_ACTIVE)
@@ -720,21 +670,18 @@ static int alsa_init_out (HWVoiceOut *hw, audsettings_t *as)
req.nchannels = as->nchannels;
req.period_size = conf.period_size_out;
req.buffer_size = conf.buffer_size_out;
+ req.size_in_usec = conf.size_in_usec_out;
+ req.override_mask = !!conf.period_size_out_overridden
+ | (!!conf.buffer_size_out_overridden << 1);
if (alsa_open (0, &req, &obt, &handle)) {
goto Exit;
}
- err = alsa_to_audfmt (obt.fmt, &effective_fmt, &endianness);
- if (err) {
- alsa_anal_close (&handle);
- goto Exit;
- }
-
obt_as.freq = obt.freq;
obt_as.nchannels = obt.nchannels;
- obt_as.fmt = effective_fmt;
- obt_as.endianness = endianness;
+ obt_as.fmt = obt.fmt;
+ obt_as.endianness = obt.endianness;
audio_pcm_init_info (&hw->info, &obt_as);
hw->samples = obt.samples;
@@ -801,11 +748,9 @@ static int alsa_init_in (HWVoiceIn *hw, audsettings_t *as)
ALSAVoiceIn *alsa = (ALSAVoiceIn *) hw;
struct alsa_params_req req;
struct alsa_params_obt obt;
- int endianness;
- int err, result = -1;
- audfmt_e effective_fmt;
snd_pcm_t *handle;
audsettings_t obt_as;
+ int result = -1;
/* shut alsa debug spew */
if (!D_ACTIVE)
@@ -816,21 +761,18 @@ static int alsa_init_in (HWVoiceIn *hw, audsettings_t *as)
req.nchannels = as->nchannels;
req.period_size = conf.period_size_in;
req.buffer_size = conf.buffer_size_in;
+ req.size_in_usec = conf.size_in_usec_in;
+ req.override_mask = !!conf.period_size_in_overridden
+ | (!!conf.buffer_size_in_overridden << 1);
if (alsa_open (1, &req, &obt, &handle)) {
goto Exit;
}
- err = alsa_to_audfmt (obt.fmt, &effective_fmt, &endianness);
- if (err) {
- alsa_anal_close (&handle);
- goto Exit;
- }
-
obt_as.freq = obt.freq;
obt_as.nchannels = obt.nchannels;
- obt_as.fmt = effective_fmt;
- obt_as.endianness = endianness;
+ obt_as.fmt = obt.fmt;
+ obt_as.endianness = obt.endianness;
audio_pcm_init_info (&hw->info, &obt_as);
hw->samples = obt.samples;
@@ -1033,16 +975,20 @@ static struct audio_option alsa_options[] = {
{"DAC_SIZE_IN_USEC", AUD_OPT_BOOL, &conf.size_in_usec_out,
"DAC period/buffer size in microseconds (otherwise in frames)", NULL, 0},
{"DAC_PERIOD_SIZE", AUD_OPT_INT, &conf.period_size_out,
- "DAC period size", &conf.period_size_out_overriden, 0},
+ "DAC period size (0 to go with system default)",
+ &conf.period_size_out_overridden, 0},
{"DAC_BUFFER_SIZE", AUD_OPT_INT, &conf.buffer_size_out,
- "DAC buffer size", &conf.buffer_size_out_overriden, 0},
+ "DAC buffer size (0 to go with system default)",
+ &conf.buffer_size_out_overridden, 0},
{"ADC_SIZE_IN_USEC", AUD_OPT_BOOL, &conf.size_in_usec_in,
"ADC period/buffer size in microseconds (otherwise in frames)", NULL, 0},
{"ADC_PERIOD_SIZE", AUD_OPT_INT, &conf.period_size_in,
- "ADC period size", &conf.period_size_in_overriden, 0},
+ "ADC period size (0 to go with system default)",
+ &conf.period_size_in_overridden, 0},
{"ADC_BUFFER_SIZE", AUD_OPT_INT, &conf.buffer_size_in,
- "ADC buffer size", &conf.buffer_size_in_overriden, 0},
+ "ADC buffer size (0 to go with system default)",
+ &conf.buffer_size_in_overridden, 0},
{"THRESHOLD", AUD_OPT_INT, &conf.threshold,
"(undocumented)", NULL, 0},
diff --git a/audio/esdaudio.c b/audio/esdaudio.c
index 636bbaf..35d6b45 100644
--- a/audio/esdaudio.c
+++ b/audio/esdaudio.c
@@ -123,6 +123,10 @@ static void *qesd_thread_out (void *arg)
threshold = conf.divisor ? hw->samples / conf.divisor : 0;
+ if (audio_pt_lock (&esd->pt, AUDIO_FUNC)) {
+ return NULL;
+ }
+
/* ignore SIGALRM in this thread */
sigemptyset(&set);
sigaddset(&set, SIGALRM);
@@ -271,13 +275,10 @@ static int qesd_init_out (HWVoiceOut *hw, audsettings_t *as)
default:
dolog ("Internal logic error: Bad audio format %d\n", as->fmt);
-#ifdef DEBUG_FMOD
- abort ();
-#endif
goto deffmt;
}
- obt_as.endianness = 0;
+ obt_as.endianness = AUDIO_HOST_ENDIANNESS;
audio_pcm_init_info (&hw->info, &obt_as);
@@ -364,6 +365,10 @@ static void *qesd_thread_in (void *arg)
threshold = conf.divisor ? hw->samples / conf.divisor : 0;
+ if (audio_pt_lock (&esd->pt, AUDIO_FUNC)) {
+ return NULL;
+ }
+
for (;;) {
int incr, to_grab, wpos;
@@ -498,7 +503,7 @@ static int qesd_init_in (HWVoiceIn *hw, audsettings_t *as)
break;
#endif
}
- obt_as.endianness = 0;
+ obt_as.endianness = AUDIO_HOST_ENDIANNESS;
audio_pcm_init_info (&hw->info, &obt_as);
diff --git a/audio/ossaudio.c b/audio/ossaudio.c
index 4d36e45..17d676a 100644
--- a/audio/ossaudio.c
+++ b/audio/ossaudio.c
@@ -231,7 +231,7 @@ static int oss_open (int in, struct oss_params *req,
goto err;
}
- if (ioctl (fd, SNDCTL_DSP_NONBLOCK)) {
+ if (ioctl (fd, SNDCTL_DSP_NONBLOCK, NULL)) {
oss_logerr2 (errno, typ, "Failed to set non-blocking mode\n");
goto err;
}
@@ -248,6 +248,12 @@ static int oss_open (int in, struct oss_params *req,
goto err;
}
+ if (!abinfo.fragstotal || !abinfo.fragsize) {
+ AUD_log(AUDIO_CAP, "Returned bogus buffer information(%d, %d) for %s\n",
+ abinfo.fragstotal, abinfo.fragsize, typ);
+ goto err;
+ }
+
obt->fmt = fmt;
obt->nchannels = nchannels;
obt->freq = freq;
diff --git a/audio/sdlaudio.c b/audio/sdlaudio.c
index 83469ac..eb353d7 100644
--- a/audio/sdlaudio.c
+++ b/audio/sdlaudio.c
@@ -25,6 +25,13 @@
#include <SDL_thread.h>
#include "vl.h"
+#ifndef _WIN32
+#ifdef __sun__
+#define _POSIX_PTHREAD_SEMANTICS 1
+#endif
+#include <signal.h>
+#endif
+
#define AUDIO_CAP "sdl"
#include "audio_int.h"
@@ -213,11 +220,21 @@ static int sdl_to_audfmt (int sdlfmt, audfmt_e *fmt, int *endianess)
static int sdl_open (SDL_AudioSpec *req, SDL_AudioSpec *obt)
{
int status;
+#ifndef _WIN32
+ sigset_t new, old;
+
+ /* Make sure potential threads created by SDL don't hog signals. */
+ sigfillset (&new);
+ pthread_sigmask (SIG_BLOCK, &new, &old);
+#endif
status = SDL_OpenAudio (req, obt);
if (status) {
sdl_logerr ("SDL_OpenAudio failed\n");
}
+#ifndef _WIN32
+ pthread_sigmask (SIG_SETMASK, &old, 0);
+#endif
return status;
}
diff --git a/framebuffer.c b/framebuffer.c
index 04177e0..d0f9b40 100644
--- a/framebuffer.c
+++ b/framebuffer.c
@@ -92,8 +92,8 @@ qframebuffer_set_dpi( QFrameBuffer* qfbuff,
** mm / 25.4 = dots / dpi
** mm = (dots * 25.4)/dpi
*/
- qfbuff->phys_width_mm = 25.4 * qfbuff->width / x_dpi;
- qfbuff->phys_height_mm = 25.4 * qfbuff->height / y_dpi;
+ qfbuff->phys_width_mm = (int)(0.5 + 25.4 * qfbuff->width / x_dpi);
+ qfbuff->phys_height_mm = (int)(0.5 + 25.4 * qfbuff->height / y_dpi);
}
/* alternative to qframebuffer_set_dpi where one can set the physical dimensions directly */
diff --git a/osdep.h b/osdep.h
index 195fd1c..7cb86da 100644
--- a/osdep.h
+++ b/osdep.h
@@ -6,6 +6,12 @@
#include <stddef.h>
#include "config.h"
+#ifndef container_of
+#define container_of(ptr, type, member) ({ \
+ const typeof(((type *) 0)->member) *__mptr = (ptr); \
+ (type *) ((char *) __mptr - offsetof(type, member));})
+#endif
+
int qemu_vsnprintf(char *buf, int buflen, const char *fmt, va_list args);
void qemu_vprintf(const char *fmt, va_list ap);
void qemu_printf(const char *fmt, ...);
diff --git a/slirp2/ip.h b/slirp2/ip.h
index 8b6ae30..8cdb735 100644
--- a/slirp2/ip.h
+++ b/slirp2/ip.h
@@ -185,35 +185,31 @@ struct ip_timestamp {
#define IP_MSS 576 /* default maximum segment size */
-#ifdef HAVE_SYS_TYPES32_H /* Overcome some Solaris 2.x junk */
-#include <sys/types32.h>
-#else
#if SIZEOF_CHAR_P == 4
-typedef caddr_t caddr32_t;
-#else
-typedef u_int32_t caddr32_t;
-#endif
-#endif
-
-#if SIZEOF_CHAR_P == 4
-typedef struct ipq *ipqp_32;
-typedef struct ipasfrag *ipasfragp_32;
+struct mbuf_ptr {
+ struct mbuf *mptr;
+ uint32_t dummy;
+};
#else
-typedef caddr32_t ipqp_32;
-typedef caddr32_t ipasfragp_32;
+struct mbuf_ptr {
+ struct mbuf *mptr;
+};
#endif
+struct qlink {
+ void* next, *prev;
+};
/*
* Overlay for ip header used by other protocols (tcp, udp).
*/
struct ipovly {
- caddr32_t ih_next, ih_prev; /* for protocol sequence q's */
+ struct mbuf_ptr ih_mbuf; /* backpointer to mbuf */
u_int8_t ih_x1; /* (unused) */
u_int8_t ih_pr; /* protocol */
u_int16_t ih_len; /* protocol length */
ipaddr_t ih_src; /* source internet address */
ipaddr_t ih_dst; /* destination internet address */
-};
+} __attribute__((packed));
/*
* Ip reassembly queue structure. Each fragment
@@ -223,44 +219,30 @@ struct ipovly {
* size 28 bytes
*/
struct ipq {
- ipqp_32 next,prev; /* to other reass headers */
+ struct qlink frag_link; /* to ip headers of fragments */
+ struct qlink ip_link; /* to other reass headers */
u_int8_t ipq_ttl; /* time for reass q to live */
u_int8_t ipq_p; /* protocol of this fragment */
u_int16_t ipq_id; /* sequence id for reassembly */
- ipasfragp_32 ipq_next,ipq_prev;
- /* to ip headers of fragments */
ipaddr_t ipq_src,ipq_dst;
};
/*
* Ip header, when holding a fragment.
*
- * Note: ipf_next must be at same offset as ipq_next above
+ * Note: ipf_next must be at same offset as frag_link above
*/
struct ipasfrag {
-#ifdef WORDS_BIGENDIAN
- u_int ip_v:4,
- ip_hl:4;
-#else
- u_int ip_hl:4,
- ip_v:4;
-#endif
- /* BUG : u_int changed to u_int8_t.
- * sizeof(u_int)==4 on linux 2.0
- */
- u_int8_t ipf_mff; /* XXX overlays ip_tos: use low bit
- * to avoid destroying tos (PPPDTRuu);
- * copied from (ip_off&IP_MF) */
- u_int16_t ip_len;
- u_int16_t ip_id;
- u_int16_t ip_off;
- u_int8_t ip_ttl;
- u_int8_t ip_p;
- u_int16_t ip_sum;
- ipasfragp_32 ipf_next; /* next fragment */
- ipasfragp_32 ipf_prev; /* previous fragment */
+ struct qlink ipf_link;
+ struct ip ipf_ip;
};
+#define ipf_off ipf_ip.ip_off
+#define ipf_tos ipf_ip.ip_tos
+#define ipf_len ipf_ip.ip_len
+#define ipf_next ipf_link.next
+#define ipf_prev ipf_link.prev
+
/*
* Structure stored in mbuf in inpcb.ip_options
* and passed to ip_output when ip options are in use.
diff --git a/slirp2/ip_input.c b/slirp2/ip_input.c
index a0013aa..7a9ebf1 100644
--- a/slirp2/ip_input.c
+++ b/slirp2/ip_input.c
@@ -43,6 +43,7 @@
*/
#include <slirp.h>
+#include <osdep.h>
#include "ip_icmp.h"
int ip_defttl;
@@ -56,7 +57,7 @@ struct ipq ipq;
void
ip_init()
{
- ipq.next = ipq.prev = (ipqp_32)&ipq;
+ ipq.ip_link.next = ipq.ip_link.prev = &ipq.ip_link;
ip_id = tt.tv_sec & 0xffff;
udp_init();
tcp_init();
@@ -159,18 +160,20 @@ ip_input(m)
*/
if (ip->ip_off &~ IP_DF) {
register struct ipq *fp;
+ struct qlink *l;
/*
* Look for queue of fragments
* of this datagram.
*/
- for (fp = (struct ipq *) ipq.next; fp != &ipq;
- fp = (struct ipq *) fp->next)
+ for (l = ipq.ip_link.next; l != &ipq.ip_link; l = l->next) {
+ fp = container_of(l, struct ipq, ip_link);
if (ip->ip_id == fp->ipq_id &&
ip_equal(ip->ip_src, fp->ipq_src) &&
ip_equal(ip->ip_dst, fp->ipq_dst) &&
ip->ip_p == fp->ipq_p)
- goto found;
- fp = 0;
+ goto found;
+ }
+ fp = NULL;
found:
/*
@@ -180,9 +183,9 @@ ip_input(m)
*/
ip->ip_len -= hlen;
if (ip->ip_off & IP_MF)
- ((struct ipasfrag *)ip)->ipf_mff |= 1;
+ ip->ip_tos |= 1;
else
- ((struct ipasfrag *)ip)->ipf_mff &= ~1;
+ ip->ip_tos &= ~1;
ip->ip_off <<= 3;
@@ -191,9 +194,9 @@ ip_input(m)
* or if this is not the first fragment,
* attempt reassembly; if it succeeds, proceed.
*/
- if (((struct ipasfrag *)ip)->ipf_mff & 1 || ip->ip_off) {
+ if (ip->ip_tos & 1 || ip->ip_off) {
ipstat.ips_fragments++;
- ip = ip_reass((struct ipasfrag *)ip, fp);
+ ip = ip_reass(ip, fp);
if (ip == 0)
return;
ipstat.ips_reassembled++;
@@ -229,6 +232,9 @@ bad:
return;
}
+#define iptofrag(P) ((struct ipasfrag *)(((char*)(P)) - sizeof(struct qlink)))
+#define fragtoip(P) ((struct ip*)(((char*)(P)) + sizeof(struct qlink)))
+
/*
* Take incoming datagram fragment and try to
* reassemble it into whole datagram. If a chain for
@@ -237,7 +243,7 @@ bad:
*/
struct ip *
ip_reass(ip, fp)
- register struct ipasfrag *ip;
+ register struct ip *ip;
register struct ipq *fp;
{
register MBuf m = MBUF_FROM(ip);
@@ -265,13 +271,13 @@ ip_reass(ip, fp)
MBuf t;
if ((t = mbuf_alloc()) == NULL) goto dropfrag;
fp = MBUF_TO(t, struct ipq *);
- insque_32(fp, &ipq);
+ insque(&fp->ip_link, &ipq.ip_link);
fp->ipq_ttl = IPFRAGTTL;
fp->ipq_p = ip->ip_p;
fp->ipq_id = ip->ip_id;
- fp->ipq_next = fp->ipq_prev = (ipasfragp_32)fp;
- fp->ipq_src = ((struct ip *)ip)->ip_src;
- fp->ipq_dst = ((struct ip *)ip)->ip_dst;
+ fp->frag_link.next = fp->frag_link.prev = &fp->frag_link;
+ fp->ipq_src = ip->ip_src;
+ fp->ipq_dst = ip->ip_src;
q = (struct ipasfrag *)fp;
goto insert;
}
@@ -279,19 +285,18 @@ ip_reass(ip, fp)
/*
* Find a segment which begins after this one does.
*/
- for (q = (struct ipasfrag *)fp->ipq_next; q != (struct ipasfrag *)fp;
- q = (struct ipasfrag *)q->ipf_next)
- if (q->ip_off > ip->ip_off)
- break;
-
+ for (q = fp->frag_link.next; q != (struct ipasfrag *)&fp->frag_link;
+ q = q->ipf_next)
+ if (q->ipf_off > ip->ip_off)
+ break;
/*
* If there is a preceding segment, it may provide some of
* our data already. If so, drop the data from the incoming
* segment. If it provides all of our data, drop us.
*/
- if (q->ipf_prev != (ipasfragp_32)fp) {
- i = ((struct ipasfrag *)(q->ipf_prev))->ip_off +
- ((struct ipasfrag *)(q->ipf_prev))->ip_len - ip->ip_off;
+ if (q->ipf_prev != &fp->frag_link) {
+ struct ipasfrag *pq = q->ipf_prev;
+ i = pq->ipf_off + pq->ipf_len - ip->ip_off;
if (i > 0) {
if (i >= ip->ip_len)
goto dropfrag;
@@ -305,17 +310,18 @@ ip_reass(ip, fp)
* While we overlap succeeding segments trim them or,
* if they are completely covered, dequeue them.
*/
- while (q != (struct ipasfrag *)fp && ip->ip_off + ip->ip_len > q->ip_off) {
- i = (ip->ip_off + ip->ip_len) - q->ip_off;
- if (i < q->ip_len) {
- q->ip_len -= i;
- q->ip_off += i;
- mbuf_trim(MBUF_FROM(q), i);
- break;
+ while (q != (struct ipasfrag *)&fp->frag_link &&
+ ip->ip_off + ip->ip_len > q->ipf_off) {
+ i = (ip->ip_off + ip->ip_len) - q->ipf_off;
+ if (i < q->ipf_len) {
+ q->ipf_len -= i;
+ q->ipf_off += i;
+ mbuf_trim(MBUF_FROM(q), i);
+ break;
}
- q = (struct ipasfrag *) q->ipf_next;
- mbuf_free(MBUF_FROM((struct ipasfrag *) q->ipf_prev));
- ip_deq((struct ipasfrag *) q->ipf_prev);
+ q = q->ipf_next;
+ mbuf_free(MBUF_FROM(q->ipf_prev));
+ ip_deq(q->ipf_prev);
}
insert:
@@ -323,27 +329,28 @@ insert:
* Stick new segment in its place;
* check for complete reassembly.
*/
- ip_enq(ip, (struct ipasfrag *) q->ipf_prev);
+ ip_enq(iptofrag(ip), q->ipf_prev);
next = 0;
- for (q = (struct ipasfrag *) fp->ipq_next; q != (struct ipasfrag *)fp;
- q = (struct ipasfrag *) q->ipf_next) {
- if (q->ip_off != next)
- return (0);
- next += q->ip_len;
+ for (q = fp->frag_link.next; q != (struct ipasfrag *)&fp->frag_link;
+ q = q->ipf_next)
+ {
+ if (q->ipf_off != next)
+ return (0);
+
+ next += q->ipf_len;
}
- if (((struct ipasfrag *)(q->ipf_prev))->ipf_mff & 1)
+ if (((struct ipasfrag *)(q->ipf_prev))->ipf_tos & 1)
return (0);
/*
* Reassembly is complete; concatenate fragments.
*/
- q = (struct ipasfrag *) fp->ipq_next;
+ q = fp->frag_link.next;
m = MBUF_FROM(q);
q = (struct ipasfrag *) q->ipf_next;
- while (q != (struct ipasfrag *)fp) {
- MBuf t;
- t = MBUF_FROM(q);
+ while (q != (struct ipasfrag *)&fp->frag_link) {
+ MBuf t = MBUF_FROM(q);
q = (struct ipasfrag *) q->ipf_next;
mbuf_append(m, t);
}
@@ -354,7 +361,7 @@ insert:
* dequeue and discard fragment reassembly header.
* Make header visible.
*/
- ip = (struct ipasfrag *) fp->ipq_next;
+ q = fp->frag_link.next;
/*
* If the fragments concatenated to an mbuf that's
@@ -366,23 +373,23 @@ insert:
if (m->m_flags & M_EXT) {
int delta;
delta = (char *)ip - m->m_dat;
- ip = (struct ipasfrag *)(m->m_ext + delta);
+ q = (struct ipasfrag *)(m->m_ext + delta);
}
/* DEBUG_ARG("ip = %lx", (long)ip);
* ip=(struct ipasfrag *)m->m_data; */
- ip->ip_len = next;
- ip->ipf_mff &= ~1;
- ((struct ip *)ip)->ip_src = fp->ipq_src;
- ((struct ip *)ip)->ip_dst = fp->ipq_dst;
- remque_32(fp);
+ ip = fragtoip(q);
+ ip->ip_len = next;
+ ip->ip_tos &= ~1;
+ ip->ip_src = fp->ipq_src;
+ ip->ip_dst = fp->ipq_dst;
+ remque(&fp->ip_link);
(void) mbuf_free(MBUF_FROM(fp));
- m = MBUF_FROM(ip);
m->m_len += (ip->ip_hl << 2);
m->m_data -= (ip->ip_hl << 2);
- return ((struct ip *)ip);
+ return ip;
dropfrag:
ipstat.ips_fragdropped++;
@@ -400,13 +407,12 @@ ip_freef(fp)
{
register struct ipasfrag *q, *p;
- for (q = (struct ipasfrag *) fp->ipq_next; q != (struct ipasfrag *)fp;
- q = p) {
- p = (struct ipasfrag *) q->ipf_next;
+ for (q = fp->frag_link.next; q != (struct ipasfrag *)&fp->frag_link; q = p) {
+ p = q->ipf_next;
ip_deq(q);
mbuf_free(MBUF_FROM(q));
}
- remque_32(fp);
+ remque(&fp->ip_link);
(void) mbuf_free(MBUF_FROM(fp));
}
@@ -420,10 +426,10 @@ ip_enq(p, prev)
{
DEBUG_CALL("ip_enq");
DEBUG_ARG("prev = %lx", (long)prev);
- p->ipf_prev = (ipasfragp_32) prev;
+ p->ipf_prev = prev;
p->ipf_next = prev->ipf_next;
- ((struct ipasfrag *)(prev->ipf_next))->ipf_prev = (ipasfragp_32) p;
- prev->ipf_next = (ipasfragp_32) p;
+ ((struct ipasfrag *)(prev->ipf_next))->ipf_prev = p;
+ prev->ipf_next = p;
}
/*
@@ -445,20 +451,20 @@ ip_deq(p)
void
ip_slowtimo()
{
- register struct ipq *fp;
+ struct qlink *l;
DEBUG_CALL("ip_slowtimo");
- fp = (struct ipq *) ipq.next;
- if (fp == 0)
+ l = ipq.ip_link.next;
+ if (l == 0)
return;
- while (fp != &ipq) {
- --fp->ipq_ttl;
- fp = (struct ipq *) fp->next;
- if (((struct ipq *)(fp->prev))->ipq_ttl == 0) {
+ while (l != &ipq.ip_link) {
+ struct ipq *fp = container_of(l, struct ipq, ip_link);
+ l = l->next;
+ if (--fp->ipq_ttl == 0) {
ipstat.ips_fragtimeout++;
- ip_freef((struct ipq *) fp->prev);
+ ip_freef(fp);
}
}
}
diff --git a/slirp2/misc.c b/slirp2/misc.c
index e34ca77..9a2699a 100644
--- a/slirp2/misc.c
+++ b/slirp2/misc.c
@@ -62,36 +62,6 @@ getouraddr()
our_addr_ip = loopback_addr_ip;
}
-#if SIZEOF_CHAR_P == 8
-
-struct quehead_32 {
- u_int32_t qh_link;
- u_int32_t qh_rlink;
-};
-
-inline void
-insque_32(void* a, void* b)
-{
- register struct quehead_32 *element = (struct quehead_32 *) a;
- register struct quehead_32 *head = (struct quehead_32 *) b;
- element->qh_link = head->qh_link;
- head->qh_link = (u_int32_t)element;
- element->qh_rlink = (u_int32_t)head;
- ((struct quehead_32 *)(element->qh_link))->qh_rlink
- = (u_int32_t)element;
-}
-
-inline void
-remque_32(void* a)
-{
- register struct quehead_32 *element = (struct quehead_32 *) a;
- ((struct quehead_32 *)(element->qh_link))->qh_rlink = element->qh_rlink;
- ((struct quehead_32 *)(element->qh_rlink))->qh_link = element->qh_link;
- element->qh_rlink = 0;
-}
-
-#endif /* SIZEOF_CHAR_P == 8 */
-
struct quehead {
struct quehead *qh_link;
struct quehead *qh_rlink;
diff --git a/slirp2/slirp.c b/slirp2/slirp.c
index d7bc545..8099aff 100644
--- a/slirp2/slirp.c
+++ b/slirp2/slirp.c
@@ -280,7 +280,7 @@ void slirp_select_fill(int *pnfds,
* in the fragment queue, or there are TCP connections active
*/
do_slowtimo = ((tcb.so_next != &tcb) ||
- ((struct ipasfrag *)&ipq != (struct ipasfrag *)ipq.next));
+ (&ipq.ip_link != ipq.ip_link.next));
for (so = tcb.so_next; so != &tcb; so = so_next) {
so_next = so->so_next;
diff --git a/slirp2/slirp.h b/slirp2/slirp.h
index bb21ff8..e69940b 100644
--- a/slirp2/slirp.h
+++ b/slirp2/slirp.h
@@ -211,14 +211,6 @@ void lprint _P((const char *, ...));
extern int do_echo;
-#if SIZEOF_CHAR_P == 4
-# define insque_32 insque
-# define remque_32 remque
-#else
- inline void insque_32 _P((void *, void *));
- inline void remque_32 _P((void *));
-#endif
-
#define DEFAULT_BAUD 115200
/* cksum.c */
@@ -231,7 +223,7 @@ void if_output _P((struct socket *, MBuf ));
/* ip_input.c */
void ip_init _P((void));
void ip_input _P((MBuf ));
-struct ip * ip_reass _P((register struct ipasfrag *, register struct ipq *));
+struct ip * ip_reass _P((register struct ip*, register struct ipq *));
void ip_freef _P((struct ipq *));
void ip_enq _P((register struct ipasfrag *, register struct ipasfrag *));
void ip_deq _P((register struct ipasfrag *));
diff --git a/slirp2/tcp_input.c b/slirp2/tcp_input.c
index 1c5a709..c3196d3 100644
--- a/slirp2/tcp_input.c
+++ b/slirp2/tcp_input.c
@@ -71,7 +71,7 @@ tcp_seq tcp_iss; /* tcp initial send seq # */
#ifdef TCP_ACK_HACK
#define TCP_REASS(tp, ti, m, so, flags) {\
if ((ti)->ti_seq == (tp)->rcv_nxt && \
- (tp)->seg_next == (tcpiphdrp_32)(tp) && \
+ tcpfrag_list_empty(tp) && \
(tp)->t_state == TCPS_ESTABLISHED) {\
if (ti->ti_flags & TH_PUSH) \
tp->t_flags |= TF_ACKNOW; \
@@ -94,7 +94,7 @@ tcp_seq tcp_iss; /* tcp initial send seq # */
#else
#define TCP_REASS(tp, ti, m, so, flags) { \
if ((ti)->ti_seq == (tp)->rcv_nxt && \
- (tp)->seg_next == (tcpiphdrp_32)(tp) && \
+ tcpfrag_list_empty(tp) && \
(tp)->t_state == TCPS_ESTABLISHED) { \
tp->t_flags |= TF_DELACK; \
(tp)->rcv_nxt += (ti)->ti_len; \
@@ -133,8 +133,8 @@ tcp_reass(tp, ti, m)
/*
* Find a segment which begins after this one does.
*/
- for (q = (struct tcpiphdr *)tp->seg_next; q != (struct tcpiphdr *)tp;
- q = (struct tcpiphdr *)q->ti_next)
+ for (q = tcpfrag_list_first(tp); !tcpfrag_list_end(q, tp);
+ q = tcpiphdr_next(q))
if (SEQ_GT(q->ti_seq, ti->ti_seq))
break;
@@ -143,9 +143,9 @@ tcp_reass(tp, ti, m)
* our data already. If so, drop the data from the incoming
* segment. If it provides all of our data, drop us.
*/
- if ((struct tcpiphdr *)q->ti_prev != (struct tcpiphdr *)tp) {
+ if (!tcpfrag_list_end(tcpiphdr_prev(q), tp)) {
register int i;
- q = (struct tcpiphdr *)q->ti_prev;
+ q = tcpiphdr_prev(q);
/* conversion to int (in i) handles seq wraparound */
i = q->ti_seq + q->ti_len - ti->ti_seq;
if (i > 0) {
@@ -165,36 +165,36 @@ tcp_reass(tp, ti, m)
ti->ti_len -= i;
ti->ti_seq += i;
}
- q = (struct tcpiphdr *)(q->ti_next);
+ q = tcpiphdr_next(q);
}
tcpstat.tcps_rcvoopack++;
tcpstat.tcps_rcvoobyte += ti->ti_len;
- REASS_MBUF(ti) = (mbufp_32) m; /* XXX */
+ ti->ti_mbuf = m;
/*
* While we overlap succeeding segments trim them or,
* if they are completely covered, dequeue them.
*/
- while (q != (struct tcpiphdr *)tp) {
+ while (!tcpfrag_list_end(q, tp)) {
register int i = (ti->ti_seq + ti->ti_len) - q->ti_seq;
if (i <= 0)
break;
if (i < q->ti_len) {
q->ti_seq += i;
q->ti_len -= i;
- mbuf_trim((MBuf ) REASS_MBUF(q), i);
+ mbuf_trim(q->ti_mbuf, i);
break;
}
- q = (struct tcpiphdr *)q->ti_next;
- m = (MBuf ) REASS_MBUF((struct tcpiphdr *)q->ti_prev);
- remque_32((void *)(q->ti_prev));
+ q = tcpiphdr_next(q);
+ m = tcpiphdr_prev(q)->ti_mbuf;
+ remque(tcpiphdr2qlink(tcpiphdr_prev(q)));
mbuf_free(m);
}
/*
* Stick new segment in its place.
*/
- insque_32(ti, (void *)(q->ti_prev));
+ insque(tcpiphdr2qlink(ti), tcpiphdr2qlink(tcpiphdr_prev(q)));
present:
/*
@@ -203,17 +203,17 @@ present:
*/
if (!TCPS_HAVEESTABLISHED(tp->t_state))
return (0);
- ti = (struct tcpiphdr *) tp->seg_next;
- if (ti == (struct tcpiphdr *)tp || ti->ti_seq != tp->rcv_nxt)
+ ti = tcpfrag_list_first(tp);
+ if (tcpfrag_list_end(ti, tp) || ti->ti_seq != tp->rcv_nxt)
return (0);
if (tp->t_state == TCPS_SYN_RECEIVED && ti->ti_len)
return (0);
do {
tp->rcv_nxt += ti->ti_len;
flags = ti->ti_flags & TH_FIN;
- remque_32(ti);
- m = (MBuf ) REASS_MBUF(ti); /* XXX */
- ti = (struct tcpiphdr *)ti->ti_next;
+ remque(tcpiphdr2qlink(ti));
+ m = ti->ti_mbuf;
+ ti = tcpiphdr_next(ti);
/* if (so->so_state & SS_FCANTRCVMORE) */
if (so->so_state & SS_FCANTSENDMORE)
mbuf_free(m);
@@ -223,7 +223,7 @@ present:
} else
sbuf_append(so, m);
}
- } while (ti != (struct tcpiphdr *)tp && ti->ti_seq == tp->rcv_nxt);
+ } while (!tcpfrag_list_end(ti, tp) && ti->ti_seq == tp->rcv_nxt);
/* sorwakeup(so); */
return (flags);
}
@@ -300,7 +300,8 @@ tcp_input(m, iphlen, inso)
* Checksum extended TCP header and data.
*/
tlen = ((struct ip *)ti)->ip_len;
- ti->ti_next = ti->ti_prev = 0;
+ tcpiphdr2qlink(ti)->next = tcpiphdr2qlink(ti)->prev = 0;
+ memset(&ti->ti_i.ih_mbuf, 0, sizeof(struct mbuf_ptr));
ti->ti_x1 = 0;
ti->ti_len = htons((u_int16_t)tlen);
len = sizeof(struct ip ) + tlen;
@@ -555,7 +556,7 @@ findso:
return;
}
} else if (ti->ti_ack == tp->snd_una &&
- tp->seg_next == (tcpiphdrp_32)tp &&
+ tcpfrag_list_empty(tp) &&
ti->ti_len <= sbuf_space(&so->so_rcv)) {
/*
* this is a pure, in-sequence data packet
diff --git a/slirp2/tcp_subr.c b/slirp2/tcp_subr.c
index fb55513..fdcb26c 100644
--- a/slirp2/tcp_subr.c
+++ b/slirp2/tcp_subr.c
@@ -85,7 +85,7 @@ tcp_template(tp)
struct socket *so = tp->t_socket;
register struct tcpiphdr *n = &tp->t_template;
- n->ti_next = n->ti_prev = 0;
+ n->ti_mbuf = NULL;
n->ti_x1 = 0;
n->ti_pr = IPPROTO_TCP;
n->ti_len = htons(sizeof (struct tcpiphdr) - sizeof (struct ip));
@@ -168,7 +168,7 @@ tcp_respond(tp, ti, m, ack, seq, flags)
tlen += sizeof (struct tcpiphdr);
m->m_len = tlen;
- ti->ti_next = ti->ti_prev = 0;
+ ti->ti_mbuf = 0;
ti->ti_x1 = 0;
ti->ti_seq = htonl(seq);
ti->ti_ack = htonl(ack);
@@ -208,7 +208,7 @@ tcp_newtcpcb(so)
return ((struct tcpcb *)0);
memset((char *) tp, 0, sizeof(struct tcpcb));
- tp->seg_next = tp->seg_prev = (tcpiphdrp_32)tp;
+ tp->seg_next = tp->seg_prev = (struct tcpiphdr*)tp;
tp->t_maxseg = tcp_mssdflt;
tp->t_flags = tcp_do_rfc1323 ? (TF_REQ_SCALE|TF_REQ_TSTMP) : 0;
@@ -284,12 +284,12 @@ tcp_close(tp)
DEBUG_ARG("tp = %lx", (long )tp);
/* free the reassembly queue, if any */
- t = (struct tcpiphdr *) tp->seg_next;
- while (t != (struct tcpiphdr *)tp) {
- t = (struct tcpiphdr *)t->ti_next;
- m = (MBuf ) REASS_MBUF((struct tcpiphdr *)t->ti_prev);
- remque_32((struct tcpiphdr *) t->ti_prev);
- mbuf_free(m);
+ t = tcpfrag_list_first(tp);
+ while (!tcpfrag_list_end(t, tp)) {
+ t = tcpiphdr_next(t);
+ m = tcpiphdr_prev(t)->ti_mbuf;
+ remque(tcpiphdr2qlink(tcpiphdr_prev(t)));
+ mbuf_free(m);
}
/* It's static */
/* if (tp->t_template)
diff --git a/slirp2/tcp_var.h b/slirp2/tcp_var.h
index b30a15d..3509ec8 100644
--- a/slirp2/tcp_var.h
+++ b/slirp2/tcp_var.h
@@ -41,18 +41,12 @@
#include "tcpip.h"
#include "tcp_timer.h"
-#if SIZEOF_CHAR_P == 4
- typedef struct tcpiphdr *tcpiphdrp_32;
-#else
- typedef u_int32_t tcpiphdrp_32;
-#endif
-
/*
* Tcp control block, one per tcp; fields:
*/
struct tcpcb {
- tcpiphdrp_32 seg_next; /* sequencing queue */
- tcpiphdrp_32 seg_prev;
+ struct tcpiphdr *seg_next; /* sequencing queue */
+ struct tcpiphdr *seg_prev;
short t_state; /* state of this connection */
short t_timer[TCPT_NTIMERS]; /* tcp timers */
short t_rxtshift; /* log(2) of rexmt exp. backoff */
@@ -171,21 +165,6 @@ struct tcpcb {
#define TCP_REXMTVAL(tp) \
(((tp)->t_srtt >> TCP_RTT_SHIFT) + (tp)->t_rttvar)
-/* XXX
- * We want to avoid doing m_pullup on incoming packets but that
- * means avoiding MBUF_FROM on the tcp reassembly code. That in turn means
- * keeping an mbuf pointer in the reassembly queue (since we might
- * have a cluster). As a quick hack, the source & destination
- * port numbers (which are no longer needed once we've located the
- * tcpcb) are overlayed with an mbuf pointer.
- */
-#if SIZEOF_CHAR_P == 4
-typedef MBuf mbufp_32;
-#else
-typedef u_int32_t mbufp_32;
-#endif
-#define REASS_MBUF(ti) (*(mbufp_32 *)&((ti)->ti_t))
-
/*
* TCP statistics.
* Many of these should be kept per connection,
diff --git a/slirp2/tcpip.h b/slirp2/tcpip.h
index 82708b0..891d699 100644
--- a/slirp2/tcpip.h
+++ b/slirp2/tcpip.h
@@ -44,8 +44,7 @@ struct tcpiphdr {
struct ipovly ti_i; /* overlaid ip structure */
struct tcphdr ti_t; /* tcp header */
};
-#define ti_next ti_i.ih_next
-#define ti_prev ti_i.ih_prev
+#define ti_mbuf ti_i.ih_mbuf.mptr
#define ti_x1 ti_i.ih_x1
#define ti_pr ti_i.ih_pr
#define ti_len ti_i.ih_len
@@ -62,6 +61,14 @@ struct tcpiphdr {
#define ti_sum ti_t.th_sum
#define ti_urp ti_t.th_urp
+#define tcpiphdr2qlink(T) ((struct qlink*)(((char*)(T)) - sizeof(struct qlink)))
+#define qlink2tcpiphdr(Q) ((struct tcpiphdr*)(((char*)(Q)) + sizeof(struct qlink)))
+#define tcpiphdr_next(T) qlink2tcpiphdr(tcpiphdr2qlink(T)->next)
+#define tcpiphdr_prev(T) qlink2tcpiphdr(tcpiphdr2qlink(T)->prev)
+#define tcpfrag_list_first(T) qlink2tcpiphdr((T)->seg_next)
+#define tcpfrag_list_end(F, T) (tcpiphdr2qlink(F) == (struct qlink*)(T))
+#define tcpfrag_list_empty(T) ((T)->seg_next == (struct tcpiphdr*)(T))
+
/*
* Just a clean way to get to the first byte
* of the packet
diff --git a/slirp2/udp.c b/slirp2/udp.c
index d4296d7..9305cfd 100644
--- a/slirp2/udp.c
+++ b/slirp2/udp.c
@@ -133,8 +133,7 @@ udp_input(m, iphlen)
* Checksum extended UDP header and data.
*/
if (udpcksum && uh->uh_sum) {
- ((struct ipovly *)ip)->ih_next = 0;
- ((struct ipovly *)ip)->ih_prev = 0;
+ memset(&((struct ipovly *)ip)->ih_mbuf, 0, sizeof(struct mbuf_ptr));
((struct ipovly *)ip)->ih_x1 = 0;
((struct ipovly *)ip)->ih_len = uh->uh_ulen;
/* keep uh_sum for ICMP reply
@@ -282,7 +281,7 @@ int udp_output2_(struct socket* so, MBuf m,
* and addresses and length put into network format.
*/
ui = MBUF_TO(m, struct udpiphdr *);
- ui->ui_next = ui->ui_prev = 0;
+ memset(&ui->ui_i.ih_mbuf, 0 , sizeof(struct mbuf_ptr));
ui->ui_x1 = 0;
ui->ui_pr = IPPROTO_UDP;
ui->ui_len = htons(m->m_len - sizeof(struct ip)); /* + sizeof (struct udphdr)); */
diff --git a/slirp2/udp.h b/slirp2/udp.h
index f1bb8c9..cadd17e 100644
--- a/slirp2/udp.h
+++ b/slirp2/udp.h
@@ -62,8 +62,7 @@ struct udpiphdr {
struct ipovly ui_i; /* overlaid ip structure */
struct udphdr ui_u; /* udp header */
};
-#define ui_next ui_i.ih_next
-#define ui_prev ui_i.ih_prev
+#define ui_mbuf ui_i.ih_mbuf.mptr
#define ui_x1 ui_i.ih_x1
#define ui_pr ui_i.ih_pr
#define ui_len ui_i.ih_len