diff options
author | The Android Open Source Project <initial-contribution@android.com> | 2009-01-15 16:12:09 -0800 |
---|---|---|
committer | The Android Open Source Project <initial-contribution@android.com> | 2009-01-15 16:12:09 -0800 |
commit | 0724eefc1939d32ff3c1c00a47ca6b8cccff1edd (patch) | |
tree | b693f74b51fc01bfc3f3de0c6d3c9ca1c77fcdf1 | |
parent | c2db2b6accc7888df514261a7240e7759df95a4c (diff) | |
download | external_qemu-0724eefc1939d32ff3c1c00a47ca6b8cccff1edd.zip external_qemu-0724eefc1939d32ff3c1c00a47ca6b8cccff1edd.tar.gz external_qemu-0724eefc1939d32ff3c1c00a47ca6b8cccff1edd.tar.bz2 |
auto import from //branches/cupcake/...@126645
-rw-r--r-- | CHANGES.TXT | 2 | ||||
-rw-r--r-- | android/vm/info.c | 54 | ||||
-rw-r--r-- | audio/alsaaudio.c | 308 | ||||
-rw-r--r-- | audio/esdaudio.c | 15 | ||||
-rw-r--r-- | audio/ossaudio.c | 8 | ||||
-rw-r--r-- | audio/sdlaudio.c | 17 | ||||
-rw-r--r-- | framebuffer.c | 4 | ||||
-rw-r--r-- | osdep.h | 6 | ||||
-rw-r--r-- | slirp2/ip.h | 64 | ||||
-rw-r--r-- | slirp2/ip_input.c | 140 | ||||
-rw-r--r-- | slirp2/misc.c | 30 | ||||
-rw-r--r-- | slirp2/slirp.c | 2 | ||||
-rw-r--r-- | slirp2/slirp.h | 10 | ||||
-rw-r--r-- | slirp2/tcp_input.c | 45 | ||||
-rw-r--r-- | slirp2/tcp_subr.c | 18 | ||||
-rw-r--r-- | slirp2/tcp_var.h | 25 | ||||
-rw-r--r-- | slirp2/tcpip.h | 11 | ||||
-rw-r--r-- | slirp2/udp.c | 5 | ||||
-rw-r--r-- | slirp2/udp.h | 3 |
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 */ @@ -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 |