OOB Shortcut for Query Hits
Raphael Manfredi <[email protected]> Sat, 31 Dec 2011 11:59:11 +0100
| Newsgroups | gmane.network.gnutella.devel |
|---|---|
| Organization | Home, Grenoble, France |
| Message-ID | <[email protected]> |
--6fOgds1i2Jhr4sRTewMvtOu9wlrd-uZfIo668iB
Content-Type: text/plain
Content-Transfer-Encoding: 7bit
Here's a new proposal that I'm submitting for your comments.
FYI, the "IPv6-Ready" specifications published earlier here have been
fully implemented in gtk-gnutella/0.98.2, released yesterday.
Happy reading,
Raphael
------------------------------------------------------------------------
Out-of-band Shortcut for Query Hits
Raphael Manfredi
<[email protected]>
December 31st, 2011
1. INTRODUCTION
Looking at the TCP traffic of a moderately well-connected ultra node (40 ultra
peers, 200 leaves) reveals that the size of relayed Gnutella messages splits
as follows:
4.86% for Pong, 44.34% Queries and 50.79% for Query Hits
Seven years after the introduction of Out-of-band query hits, there are still
a number of Gnutella clients out there that do not honor the OOB flag in
queries and send their query hits through TCP.
This is a cause of concern because the relaying of query hits through Gnutella
causes traffic bottlenecks and flow-control, resulting in the dropping of
less important messages such as queries, and messes up the dynamic querying
algorithms which monitor the amount of hits received to measure the popularity
of the query, due to the delayed receiving of the query hits.
This OOB Shortcut for Query Hits ("OSQH" for short) proposal aims at fixing
some of the problem at the cost of more intensive processing and resource
consumption within ultra peers. However, ultra peers are the backbone of
the Gnutella network, and these node can trade off some computing resources
to save some TCP bandwidth.
2. OVERVIEW
The OSQH feature works thusly:
Ultra nodes already track all the queries that pass through them to avoid
duplicates. For all the queries that are stored in their routing table,
they know need to track a few extra information:
- Whether the query requested OOB query hit delivery.
- The IPv4:port or IPv6:port where query hits should be delivered via OOB.
- For secure OOB, the query security token.
For IPv6 address information in queries, please refer to the IPv6-Ready
specifications which all modern servents should implement.
When query hits come back via TCP and they have more than one hop to go
before reaching their destination (TTL > 1 after local decrement), ultra nodes
look at whether the corresponding query was flagged with OOB by consulting
their routing table.
If no, then the query hit is normally routed via TCP as currently done.
If yes however, the query hit is buffered locally and after some time (to
accumulate more hits), an OOB Reply Indication is sent to the OOB destination
(as remembered in the routing table) via a LIME/12v2 or LIME/12v3 message.
The "flag" byte of the OOB Reply Indication message is extended and 0x2 is
OR-ed to the already defined "firewalled-flag" (0x1). The 0x2 bit indicates
that the hits come from a relaying ultrapeer, and were not generated by that
ultrapeer. This additional information can be ignored by the receiving party
or be used to activate special logic to claim all the reported hits and not
just a few.
Upon reception of the OOB Reply Indication message, the querying party will
then proceed with claiming the hits, in which case the ultra peer unbuffers
the requested amount of hits. If more hits were buffered since the indication,
another OOB Reply Indication is sent after all the initial hits have been
claimed.
Note that the amount of hits advertised in LIME/12 is NOT the amount of
query hit messages but the sum of all the individual entries held in each
query hit.
If the servent claims 255 hits (the maximum that can be possibly requested),
the ultra peer delivers entire query hit messages until the limit of 255 hits
is reached, after which if there is additional information left, it will send
another OOB Reply Indication message. This avoids flooding the receiving
end by controlling the amount of traffic that can be received.
If the servent claims less than 255 hits, it means the querying party is no
longer interested and the query can be flagged as "done" in the routing table.
Any further hit received for that query can be safely discarded.
Because UDP traffic can be lost and because this can result in the querying
party being shadowed from a potentially large amount of hits, the ultra peer
resends the OOB Reply Indication message two more times if it does not receive
any claim after some time, doubling the period each time. There is no way for
the receiver to know that this is a re-emission, and it could be confused with
an indication that there are more hits to claim.
Therefore, the ultra node will send a new GTKG/11v1 message to indicate that
there are no more hits to claim for that query, which will also serve as an
acknowledgement to the querying party if it attempts to resend a claiming
request because it thinks the previous one got lost: lack of reception of any
query hit back for the query or lack of reception of a GTKG/11v1 after some
time will indeed indicate the likelihood that some messages were dropped.
The GTKG/11v1 is specific to this OSQH proposal and is not sent back during
the regular OOB query hit delivery that would happen between a node having
results to send back and a querying party.
If the querying party does not claim the buffered hits after some reasonable
time (and after 3 notifications), the hits are dropped and the query is marked
as "done".
3. SPECIFICATION DETAILS
3.1 Gnutella Connections
An ultrapeer supporting OSQH will advertise this in its "features supported"
vendor message to let its peers know about it ("OSQH", version 1). Optionally
it can also be included in the Gnutella handshaking headers, in the X-Features
line, as version 0.1, such as:
X-Features: OSQH/0.1
in case Gnutella ultra peers want to favor connections to other OSQH-supporting
peers to reduce their query hit routing.
3.2 GTKG/11v1 -- OOB Hit Exhaustion
This vendor message is specified thusly:
Name: "OOB Hit Exhaustion"
Vendor: GTKG
ID: 11
Version: 1
TTL: 1
Payload: None
The MUID of the vendor message matches the query's MUID.
Upon reception of this message, the querying party knows that there will be
no more hits returned by the remote ultra peer for this query, so it can
stop asking.
3.3 UDP Traffic Compression
The exchanges made via OSQH are naturally suitable for UDP traffic compression,
as specified on August 13th, 2006. This is a negotiated feature so it is not
a pre-requisite for OSQH, although its support is strongly advised.
Raphael
--6fOgds1i2Jhr4sRTewMvtOu9wlrd-uZfIo668iB
Content-Type: text/html; charset=US-ASCII
Content-Transfer-Encoding: 7bit
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
</head>
<body style="background-color: #fff;">
<span style="display:none"> </span>
<!--~-|**|PrettyHtmlStartT|**|-~-->
<div id="ygrp-mlmsg" style="position:relative;">
<div id="ygrp-msg" style="z-index: 1;">
<!--~-|**|PrettyHtmlEndT|**|-~-->
<div id="ygrp-text" >
<p>Here's a new proposal that I'm submitting for your comments.<br>
<br>
FYI, the "IPv6-Ready" specifications published earlier here have been<br>
fully implemented in gtk-gnutella/0.98.2, released yesterday.<br>
<br>
Happy reading,<br>
Raphael<br>
<br>
----------------------------------------------------------<br>
Out-of-band Shortcut for Query Hits<br>
<br>
Raphael Manfredi<br>
<<a href="mailto:Raphael_Manfredi%40pobox.com">[email protected]</a>><br>
December 31st, 2011<br>
<br>
1. INTRODUCTION<br>
<br>
Looking at the TCP traffic of a moderately well-connected ultra node (40 ultra<br>
peers, 200 leaves) reveals that the size of relayed Gnutella messages splits<br>
as follows:<br>
<br>
4.86% for Pong, 44.34% Queries and 50.79% for Query Hits<br>
<br>
Seven years after the introduction of Out-of-band query hits, there are still<br>
a number of Gnutella clients out there that do not honor the OOB flag in<br>
queries and send their query hits through TCP.<br>
<br>
This is a cause of concern because the relaying of query hits through Gnutella<br>
causes traffic bottlenecks and flow-control, resulting in the dropping of<br>
less important messages such as queries, and messes up the dynamic querying<br>
algorithms which monitor the amount of hits received to measure the popularity<br>
of the query, due to the delayed receiving of the query hits.<br>
<br>
This OOB Shortcut for Query Hits ("OSQH" for short) proposal aims at fixing<br>
some of the problem at the cost of more intensive processing and resource<br>
consumption within ultra peers. However, ultra peers are the backbone of<br>
the Gnutella network, and these node can trade off some computing resources<br>
to save some TCP bandwidth.<br>
<br>
2. OVERVIEW<br>
<br>
The OSQH feature works thusly:<br>
<br>
Ultra nodes already track all the queries that pass through them to avoid<br>
duplicates. For all the queries that are stored in their routing table,<br>
they know need to track a few extra information:<br>
<br>
- Whether the query requested OOB query hit delivery.<br>
- The IPv4:port or IPv6:port where query hits should be delivered via OOB.<br>
- For secure OOB, the query security token.<br>
<br>
For IPv6 address information in queries, please refer to the IPv6-Ready<br>
specifications which all modern servents should implement.<br>
<br>
When query hits come back via TCP and they have more than one hop to go<br>
before reaching their destination (TTL > 1 after local decrement), ultra nodes<br>
look at whether the corresponding query was flagged with OOB by consulting<br>
their routing table.<br>
<br>
If no, then the query hit is normally routed via TCP as currently done.<br>
<br>
If yes however, the query hit is buffered locally and after some time (to<br>
accumulate more hits), an OOB Reply Indication is sent to the OOB destination<br>
(as remembered in the routing table) via a LIME/12v2 or LIME/12v3 message.<br>
<br>
The "flag" byte of the OOB Reply Indication message is extended and 0x2 is<br>
OR-ed to the already defined "firewalled-flag" (0x1). The 0x2 bit indicates<br>
that the hits come from a relaying ultrapeer, and were not generated by that<br>
ultrapeer. This additional information can be ignored by the receiving party<br>
or be used to activate special logic to claim all the reported hits and not<br>
just a few.<br>
<br>
Upon reception of the OOB Reply Indication message, the querying party will<br>
then proceed with claiming the hits, in which case the ultra peer unbuffers<br>
the requested amount of hits. If more hits were buffered since the indication,<br>
another OOB Reply Indication is sent after all the initial hits have been<br>
claimed.<br>
<br>
Note that the amount of hits advertised in LIME/12 is NOT the amount of<br>
query hit messages but the sum of all the individual entries held in each<br>
query hit.<br>
<br>
If the servent claims 255 hits (the maximum that can be possibly requested),<br>
the ultra peer delivers entire query hit messages until the limit of 255 hits<br>
is reached, after which if there is additional information left, it will send<br>
another OOB Reply Indication message. This avoids flooding the receiving<br>
end by controlling the amount of traffic that can be received.<br>
<br>
If the servent claims less than 255 hits, it means the querying party is no<br>
longer interested and the query can be flagged as "done" in the routing table.<br>
Any further hit received for that query can be safely discarded.<br>
<br>
Because UDP traffic can be lost and because this can result in the querying<br>
party being shadowed from a potentially large amount of hits, the ultra peer<br>
resends the OOB Reply Indication message two more times if it does not receive<br>
any claim after some time, doubling the period each time. There is no way for<br>
the receiver to know that this is a re-emission, and it could be confused with<br>
an indication that there are more hits to claim.<br>
<br>
Therefore, the ultra node will send a new GTKG/11v1 message to indicate that<br>
there are no more hits to claim for that query, which will also serve as an<br>
acknowledgement to the querying party if it attempts to resend a claiming<br>
request because it thinks the previous one got lost: lack of reception of any<br>
query hit back for the query or lack of reception of a GTKG/11v1 after some<br>
time will indeed indicate the likelihood that some messages were dropped.<br>
<br>
The GTKG/11v1 is specific to this OSQH proposal and is not sent back during<br>
the regular OOB query hit delivery that would happen between a node having<br>
results to send back and a querying party.<br>
<br>
If the querying party does not claim the buffered hits after some reasonable<br>
time (and after 3 notifications), the hits are dropped and the query is marked<br>
as "done".<br>
<br>
3. SPECIFICATION DETAILS<br>
<br>
3.1 Gnutella Connections<br>
<br>
An ultrapeer supporting OSQH will advertise this in its "features supported"<br>
vendor message to let its peers know about it ("OSQH", version 1). Optionally<br>
it can also be included in the Gnutella handshaking headers, in the X-Features<br>
line, as version 0.1, such as:<br>
<br>
X-Features: OSQH/0.1<br>
<br>
in case Gnutella ultra peers want to favor connections to other OSQH-supporting<br>
peers to reduce their query hit routing.<br>
<br>
3.2 GTKG/11v1 -- OOB Hit Exhaustion<br>
<br>
This vendor message is specified thusly:<br>
<br>
Name: "OOB Hit Exhaustion"<br>
Vendor: GTKG<br>
ID: 11<br>
Version: 1<br>
TTL: 1<br>
Payload: None<br>
<br>
The MUID of the vendor message matches the query's MUID.<br>
<br>
Upon reception of this message, the querying party knows that there will be<br>
no more hits returned by the remote ultra peer for this query, so it can<br>
stop asking.<br>
<br>
3.3 UDP Traffic Compression<br>
<br>
The exchanges made via OSQH are naturally suitable for UDP traffic compression,<br>
as specified on August 13th, 2006. This is a negotiated feature so it is not<br>
a pre-requisite for OSQH, although its support is strongly advised.<br>
<br>
Raphael<br>
</p>
</div>
<!--~-|**|PrettyHtmlStart|**|-~-->
<div style="color: #fff; height: 0;">__._,_.___</div>
<div id="ygrp-actbar" style="clear: both; margin-bottom: 10px; white-space: nowrap; color: #666; padding-top: 15px;">
<div>
<a href="mailto:[email protected]?subject=Re%3A%20OOB%20Shortcut%20for%20Query%20Hits" style="margin-right: 0; padding-right: 0;">
Reply to <span style="font-weight: 700;">sender</span></a> |
<a href="mailto:[email protected]?subject=Re%3A%20OOB%20Shortcut%20for%20Query%20Hits">
Reply to <span style="font-weight: 700;">group</span></a> |
<a href="http://groups.yahoo.com/group/the_gdf/post;_ylc=X3oDMTJxczZxa2prBF9TAzk3MzU5NzE0BGdycElkAzI2ODQyNTMEZ3Jwc3BJZAMxNzA1MDE2MDYxBG1zZ0lkAzIzNzk2BHNlYwNmdHIEc2xrA3JwbHkEc3RpbWUDMTMyNTMyOTE2NQ--?act=reply&messageNum=23796">Reply <span style="font-weight: 700;">via web post</span></a> |
<a href="http://groups.yahoo.com/group/the_gdf/post;_ylc=X3oDMTJlb2FpODFyBF9TAzk3MzU5NzE0BGdycElkAzI2ODQyNTMEZ3Jwc3BJZAMxNzA1MDE2MDYxBHNlYwNmdHIEc2xrA250cGMEc3RpbWUDMTMyNTMyOTE2NQ--" style="font-weight: 700;">Start a New Topic</a>
</div>
<a href="http://groups.yahoo.com/group/the_gdf/message/23796;_ylc=X3oDMTM2OXJnbnRjBF9TAzk3MzU5NzE0BGdycElkAzI2ODQyNTMEZ3Jwc3BJZAMxNzA1MDE2MDYxBG1zZ0lkAzIzNzk2BHNlYwNmdHIEc2xrA3Z0cGMEc3RpbWUDMTMyNTMyOTE2NQR0cGNJZAMyMzc5Ng--">Messages in this topic</a>
(<span style="font-weight: 700;">1</span>)
</div>
<!------- Start Nav Bar ------>
<!-- |**|begin egp html banner|**| -->
<div id="ygrp-vital" style="background-color: #e0ecee; font-family: Verdana; font-size: 10px; margin-bottom: 10px; padding: 10px;">
<span id="vithd" style="font-weight: bold; color: #333; text-transform: uppercase; ">Recent Activity:</span>
<ul style="list-style-type: none; margin: 0; padding: 0; display: inline;">
<li style="border-right: 1px solid #000; font-weight: 700; display: inline; padding: 0 5px; margin-left: 0;">
<span class="cat"><a href="http://groups.yahoo.com/group/the_gdf/members;_ylc=X3oDMTJmM3QzcWdkBF9TAzk3MzU5NzE0BGdycElkAzI2ODQyNTMEZ3Jwc3BJZAMxNzA1MDE2MDYxBHNlYwN2dGwEc2xrA3ZtYnJzBHN0aW1lAzEzMjUzMjkxNjU-?o=6" style="text-decoration: none;">New Members</a></span>
<span class="ct" style="color: #ff7900;">4</span>
</li>
<li style="border-right: 1px solid #000; font-weight: 700; display: inline; padding: 0 5px; margin-left: 0;">
<span class="cat"><a href="http://groups.yahoo.com/group/the_gdf/links;_ylc=X3oDMTJnYmFodnNuBF9TAzk3MzU5NzE0BGdycElkAzI2ODQyNTMEZ3Jwc3BJZAMxNzA1MDE2MDYxBHNlYwN2dGwEc2xrA3ZsaW5rcwRzdGltZQMxMzI1MzI5MTY1" style="text-decoration: none;">New Links</a></span>
<span class="ct" style="color: #ff7900;">11</span>
</li>
</ul>
<div style="clear: both; padding-top: 2px; color: #1e66ae;">
<a href="http://groups.yahoo.com/group/the_gdf;_ylc=X3oDMTJlbjJvZnQwBF9TAzk3MzU5NzE0BGdycElkAzI2ODQyNTMEZ3Jwc3BJZAMxNzA1MDE2MDYxBHNlYwN2dGwEc2xrA3ZnaHAEc3RpbWUDMTMyNTMyOTE2NQ--" style="text-decoration: none;">Visit Your Group</a>
</div>
</div>
<div id="ygrp-mkp" style="border: 1px solid #d8d8d8; clear: both; float: left; font-family: Arial; margin: 5px 0 10px 0; padding: 0 10px;">
<div id="hd" style="color: #628c2a; font-size: 85%; font-weight: 700; line-height: 122%; margin: 10px 0;">MARKETPLACE</div>
<div id="ads" style="margin-bottom: 10px;">
<div class="ad" style="color: #628C2A; font-family: Arial; font-weight: 700; padding: 0 0;">
<p><a href="http://global.ard.yahoo.com/SIG=15od8cjl5/M=493064.14543979.14562481.13298430/D=groups/S=1705016061:MKP1/Y=YAHOO/EXP=1325336365/L=80a0a5ac-339e-11e1-bee4-97f47694387f/B=zRtzANGDJGI-/J=1325329165391750/K=S02U50qfath6xETxjAye3A/A=6060255/R=0/SIG=1194m4keh/*http://us.toolbar.yahoo.com/?.cpdl=grpj">Stay on top of your group activity without leaving the page you're on - Get the Yahoo! Toolbar now.</a></p> <script language=javascript>
if(window.yzq_d==null)window.yzq_d=new Object();
window.yzq_d['zRtzANGDJGI-']='&U=13colvrs8%2fN%3dzRtzANGDJGI-%2fC%3d493064.14543979.14562481.13298430%2fD%3dMKP1%2fB%3d6060255%2fV%3d1';
</script><noscript><img width=1 height=1 alt="" src="http://us.bc.yahoo.com/b?P=80a0a5ac-339e-11e1-bee4-97f47694387f&T=1d9708qbj%2fX%3d1325329165%2fE%3d1705016061%2fR%3dgroups%2fK%3d5%2fV%3d2.1%2fW%3dH%2fY%3dYAHOO%2fF%3d1280567851%2fH%3dY29udGVudD0iR3JvdXBzO1dlYnNpdGVfU2VydmljZXM7UG9sbHM7QnJpZWZjYXNlO0ZsaWNrcjtHZW9jaXRpZXM7UGhvdG9zO1lhaG9vX1RlY2g7TWVtYmVyX0RpcmVjdG9yeTtQb2RjYXN0czsiIGRpc2FibGVzaHVmZmxpbmc9IjEiIHNlcnZlSWQ9IjgwYTBhNWFjLTMzOWUtMTFlMS1iZWU0LTk3ZjQ3Njk0Mzg3ZiIgc2l0ZUlkPSI0NDUyNTUxIiB0U3RtcD0iMTMyNTMyOTE2NTM2OTAyOCIg%2fQ%3d-1%2fS%3d1%2fJ%3d9E238962&U=13colvrs8%2fN%3dzRtzANGDJGI-%2fC%3d493064.14543979.14562481.13298430%2fD%3dMKP1%2fB%3d6060255%2fV%3d1"></noscript><!--QYZ ,;;MKP1;1705016061;2;--> </div>
</div>
</div>
<div id="ft" style="font-family: Arial; font-size: 11px; margin-top: 5px; padding: 0 2px 0 0; clear: both;">
<a href="http://groups.yahoo.com/;_ylc=X3oDMTJkbzg0aTZkBF9TAzk3MzU5NzE0BGdycElkAzI2ODQyNTMEZ3Jwc3BJZAMxNzA1MDE2MDYxBHNlYwNmdHIEc2xrA2dmcARzdGltZQMxMzI1MzI5MTY1" style="float: left;"><img src="http://l.yimg.com/a/i/us/yg/logo/us.gif" height="15" width="137" alt="Yahoo! Groups" style="border: 0;"/></a>
<div style="color: #747575; float: right;">Switch to: <a href="mailto:[email protected]?subject=Change Delivery Format: Traditional" style="text-decoration: none;">Text-Only</a>, <a href="mailto:[email protected]?subject=Email Delivery: Digest" class="margin-rt" style="text-decoration: none;">Daily Digest</a> • <a href="mailto:[email protected]?subject=Unsubscribe" style="text-decoration: none;">Unsubscribe</a> • <a href="http://docs.yahoo.com/info/terms/" style="text-decoration: none;">Terms of Use</a></div>
</div>
<!-- |**|end egp html banner|**| -->
</div> <!-- ygrp-msg -->
<!-- Sponsor -->
<!-- |**|begin egp html banner|**| -->
<div id="ygrp-sponsor" style="width:160px; float:right; clear:none; margin:0 0 25px 0; background: #fff;">
<!-- Start Recommendations -->
<div id="ygrp-reco">
</div>
<!-- End Recommendations -->
</div> <!-- |**|end egp html banner|**| -->
<div style="clear:both; color: #FFF; font-size:1px;">.</div>
</div>
<img src="http://geo.yahoo.com/serv?s=97359714/grpId=2684253/grpspId=1705016061/msgId=23796/stime=1325329165/nc1=5741392/nc2=5191955/nc3=5758219" width="1" height="1"> <br>
<div style="color: #fff; height: 0;">__,_._,___</div>
<!--~-|**|PrettyHtmlEnd|**|-~-->
</body>
<!--~-|**|PrettyHtmlStart|**|-~-->
<head>
<style type="text/css">
<!--
#ygrp-mkp {
border: 1px solid #d8d8d8;
font-family: Arial;
margin: 10px 0;
padding: 0 10px;
}
#ygrp-mkp hr {
border: 1px solid #d8d8d8;
}
#ygrp-mkp #hd {
color: #628c2a;
font-size: 85%;
font-weight: 700;
line-height: 122%;
margin: 10px 0;
}
#ygrp-mkp #ads {
margin-bottom: 10px;
}
#ygrp-mkp .ad {
padding: 0 0;
}
#ygrp-mkp .ad p {
margin: 0;
}
#ygrp-mkp .ad a {
color: #0000ff;
text-decoration: none;
}
#ygrp-sponsor #ygrp-lc {
font-family: Arial;
}
#ygrp-sponsor #ygrp-lc #hd {
margin: 10px 0px;
font-weight: 700;
font-size: 78%;
line-height: 122%;
}
#ygrp-sponsor #ygrp-lc .ad {
margin-bottom: 10px;
padding: 0 0;
}
a {
color: #1e66ae;
}
#actions {
font-family: Verdana;
font-size: 11px;
padding: 10px 0;
}
#activity {
background-color: #e0ecee;
float: left;
font-family: Verdana;
font-size: 10px;
padding: 10px;
}
#activity span {
font-weight: 700;
}
#activity span:first-child {
text-transform: uppercase;
}
#activity span a {
color: #5085b6;
text-decoration: none;
}
#activity span span {
color: #ff7900;
}
#activity span .underline {
text-decoration: underline;
}
.attach {
clear: both;
display: table;
font-family: Arial;
font-size: 12px;
padding: 10px 0;
width: 400px;
}
.attach div a {
text-decoration: none;
}
.attach img {
border: none;
padding-right: 5px;
}
.attach label {
display: block;
margin-bottom: 5px;
}
.attach label a {
text-decoration: none;
}
blockquote {
margin: 0 0 0 4px;
}
.bold {
font-family: Arial;
font-size: 13px;
font-weight: 700;
}
.bold a {
text-decoration: none;
}
dd.last p a {
font-family: Verdana;
font-weight: 700;
}
dd.last p span {
margin-right: 10px;
font-family: Verdana;
font-weight: 700;
}
dd.last p span.yshortcuts {
margin-right: 0;
}
div.attach-table div div a {
text-decoration: none;
}
div.attach-table {
width: 400px;
}
div.file-title a, div.file-title a:active, div.file-title a:hover, div.file-title a:visited {
text-decoration: none;
}
div.photo-title a, div.photo-title a:active, div.photo-title a:hover, div.photo-title a:visited {
text-decoration: none;
}
div#ygrp-mlmsg #ygrp-msg p a span.yshortcuts {
font-family: Verdana;
font-size: 10px;
font-weight: normal;
}
.green {
color: #628c2a;
}
.MsoNormal {
margin: 0 0 0 0;
}
o {
font-size: 0;
}
#photos div {
float: left;
width: 72px;
}
#photos div div {
border: 1px solid #666666;
height: 62px;
overflow: hidden;
width: 62px;
}
#photos div label {
color: #666666;
font-size: 10px;
overflow: hidden;
text-align: center;
white-space: nowrap;
width: 64px;
}
#reco-category {
font-size: 77%;
}
#reco-desc {
font-size: 77%;
}
.replbq {
margin: 4px;
}
#ygrp-actbar div a:first-child {
/* border-right: 0px solid #000;*/
margin-right: 2px;
padding-right: 5px;
}
#ygrp-mlmsg {
font-size: 13px;
font-family: Arial, helvetica,clean, sans-serif;
*font-size: small;
*font: x-small;
}
#ygrp-mlmsg table {
font-size: inherit;
font: 100%;
}
#ygrp-mlmsg select, input, textarea {
font: 99% Arial, Helvetica, clean, sans-serif;
}
#ygrp-mlmsg pre, code {
font:115% monospace;
*font-size:100%;
}
#ygrp-mlmsg * {
line-height: 1.22em;
}
#ygrp-mlmsg #logo {
padding-bottom: 10px;
}
#ygrp-mlmsg a {
color: #1E66AE;
}
#ygrp-msg p a {
font-family: Verdana;
}
#ygrp-msg p#attach-count span {
color: #1E66AE;
font-weight: 700;
}
#ygrp-reco #reco-head {
color: #ff7900;
font-weight: 700;
}
#ygrp-reco {
margin-bottom: 20px;
padding: 0px;
}
#ygrp-sponsor #ov li a {
font-size: 130%;
text-decoration: none;
}
#ygrp-sponsor #ov li {
font-size: 77%;
list-style-type: square;
padding: 6px 0;
}
#ygrp-sponsor #ov ul {
margin: 0;
padding: 0 0 0 8px;
}
#ygrp-text {
font-family: Georgia;
}
#ygrp-text p {
margin: 0 0 1em 0;
}
#ygrp-text tt {
font-size: 120%;
}
#ygrp-vital ul li:last-child {
border-right: none !important;
}
-->
</style>
</head>
<!--~-|**|PrettyHtmlEnd|**|-~-->
</html>
<!-- end group email -->
--6fOgds1i2Jhr4sRTewMvtOu9wlrd-uZfIo668iB--